1use tokio_util::sync::CancellationToken;
2
3use crate::ids::{CorrelationId, MessageId};
4
5#[derive(Debug, Clone)]
11pub struct HandlerContext {
12 pub message_id: MessageId,
14 pub correlation_id: CorrelationId,
16 pub cancellation: CancellationToken,
18 pub span: tracing::Span,
20}
21
22impl HandlerContext {
23 #[must_use]
28 pub fn new(message_id: MessageId, correlation_id: CorrelationId) -> Self {
29 Self {
30 message_id,
31 correlation_id,
32 cancellation: CancellationToken::new(),
33 span: tracing::Span::current(),
34 }
35 }
36
37 #[must_use]
40 pub fn with_span(mut self, span: tracing::Span) -> Self {
41 self.span = span;
42 self
43 }
44
45 #[must_use]
48 pub fn with_cancellation(mut self, token: CancellationToken) -> Self {
49 self.cancellation = token;
50 self
51 }
52
53 #[must_use]
55 pub fn is_cancelled(&self) -> bool {
56 self.cancellation.is_cancelled()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn new_context_is_not_cancelled() {
66 let ctx = HandlerContext::new(MessageId::new(), CorrelationId::new());
67 assert!(!ctx.is_cancelled());
68 }
69
70 #[test]
71 fn cancellation_propagates_from_parent() {
72 let parent = CancellationToken::new();
73 let child = parent.child_token();
74 let ctx =
75 HandlerContext::new(MessageId::new(), CorrelationId::new()).with_cancellation(child);
76
77 assert!(!ctx.is_cancelled());
78 parent.cancel();
79 assert!(ctx.is_cancelled());
80 }
81
82 #[test]
83 fn context_is_clone() {
84 let ctx = HandlerContext::new(MessageId::new(), CorrelationId::new());
85 let cloned = ctx.clone();
86 assert_eq!(ctx.message_id, cloned.message_id);
87 assert_eq!(ctx.correlation_id, cloned.correlation_id);
88 }
89}