webhooks (#1)
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
112
k-tv-backend/domain/src/events.rs
Normal file
112
k-tv-backend/domain/src/events.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
//! Domain events emitted when important state transitions occur.
|
||||
//!
|
||||
//! These are pure data — no I/O, no tokio deps. The transport
|
||||
//! (tokio::sync::broadcast) lives in `api`; domain only owns the schema.
|
||||
|
||||
use uuid::Uuid;
|
||||
use crate::entities::{Channel, GeneratedSchedule, ScheduledSlot};
|
||||
|
||||
/// Events emitted by the application when important state changes occur.
|
||||
///
|
||||
/// Must be `Clone + Send + 'static` for use as a `broadcast::channel` item.
|
||||
#[derive(Clone)]
|
||||
pub enum DomainEvent {
|
||||
BroadcastTransition {
|
||||
channel_id: Uuid,
|
||||
slot: ScheduledSlot,
|
||||
},
|
||||
NoSignal {
|
||||
channel_id: Uuid,
|
||||
},
|
||||
ScheduleGenerated {
|
||||
channel_id: Uuid,
|
||||
schedule: GeneratedSchedule,
|
||||
},
|
||||
ChannelCreated {
|
||||
channel: Channel,
|
||||
},
|
||||
ChannelUpdated {
|
||||
channel: Channel,
|
||||
},
|
||||
ChannelDeleted {
|
||||
channel_id: Uuid,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn make_slot() -> crate::entities::ScheduledSlot {
|
||||
use crate::entities::{MediaItem, ScheduledSlot};
|
||||
use crate::value_objects::{ContentType, MediaItemId};
|
||||
use chrono::Utc;
|
||||
ScheduledSlot {
|
||||
id: Uuid::new_v4(),
|
||||
start_at: Utc::now(),
|
||||
end_at: Utc::now() + chrono::Duration::minutes(30),
|
||||
item: MediaItem {
|
||||
id: MediaItemId::new("test-item".to_string()),
|
||||
title: "Test Movie".to_string(),
|
||||
content_type: ContentType::Movie,
|
||||
duration_secs: 1800,
|
||||
description: None,
|
||||
genres: vec![],
|
||||
year: None,
|
||||
tags: vec![],
|
||||
series_name: None,
|
||||
season_number: None,
|
||||
episode_number: None,
|
||||
},
|
||||
source_block_id: Uuid::new_v4(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn broadcast_transition_carries_slot() {
|
||||
let channel_id = Uuid::new_v4();
|
||||
let slot = make_slot();
|
||||
let event = DomainEvent::BroadcastTransition { channel_id, slot: slot.clone() };
|
||||
match event {
|
||||
DomainEvent::BroadcastTransition { channel_id: cid, slot: s } => {
|
||||
assert_eq!(cid, channel_id);
|
||||
assert_eq!(s.item.title, "Test Movie");
|
||||
}
|
||||
_ => panic!("wrong variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_signal_carries_channel_id() {
|
||||
let channel_id = Uuid::new_v4();
|
||||
let event = DomainEvent::NoSignal { channel_id };
|
||||
match event {
|
||||
DomainEvent::NoSignal { channel_id: cid } => assert_eq!(cid, channel_id),
|
||||
_ => panic!("wrong variant"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn schedule_generated_carries_metadata() {
|
||||
use crate::entities::GeneratedSchedule;
|
||||
use chrono::Utc;
|
||||
let channel_id = Uuid::new_v4();
|
||||
let schedule = GeneratedSchedule {
|
||||
id: Uuid::new_v4(),
|
||||
channel_id,
|
||||
valid_from: Utc::now(),
|
||||
valid_until: Utc::now() + chrono::Duration::hours(48),
|
||||
generation: 3,
|
||||
slots: vec![],
|
||||
};
|
||||
let event = DomainEvent::ScheduleGenerated { channel_id, schedule: schedule.clone() };
|
||||
match event {
|
||||
DomainEvent::ScheduleGenerated { schedule: s, .. } => {
|
||||
assert_eq!(s.generation, 3);
|
||||
assert_eq!(s.slots.len(), 0);
|
||||
}
|
||||
_ => panic!("wrong variant"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user