1use crate::runtime::RuntimeHandle;
7use std::sync::Arc;
8
9#[derive(Clone)]
14pub struct ProducerContext {
15 runtime: Option<Arc<dyn RuntimeHandle>>,
16}
17
18impl ProducerContext {
19 pub fn new() -> Self {
21 Self { runtime: None }
22 }
23
24 pub fn with_runtime(mut self, runtime: Arc<dyn RuntimeHandle>) -> Self {
26 self.runtime = Some(runtime);
27 self
28 }
29
30 pub fn runtime(&self) -> Option<&Arc<dyn RuntimeHandle>> {
32 self.runtime.as_ref()
33 }
34}
35
36impl Default for ProducerContext {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::CamelError;
46 use crate::runtime::{
47 RuntimeCommand, RuntimeCommandBus, RuntimeCommandResult, RuntimeQuery, RuntimeQueryBus,
48 RuntimeQueryResult,
49 };
50 use async_trait::async_trait;
51 use futures::executor::block_on;
52
53 struct NoopRuntime;
54
55 #[async_trait]
56 impl RuntimeCommandBus for NoopRuntime {
57 async fn execute(&self, _cmd: RuntimeCommand) -> Result<RuntimeCommandResult, CamelError> {
58 Ok(RuntimeCommandResult::Accepted)
59 }
60 }
61
62 #[async_trait]
63 impl RuntimeQueryBus for NoopRuntime {
64 async fn ask(&self, _query: RuntimeQuery) -> Result<RuntimeQueryResult, CamelError> {
65 Ok(RuntimeQueryResult::Routes { route_ids: vec![] })
66 }
67 }
68
69 #[test]
70 fn producer_context_new_is_empty() {
71 let ctx = ProducerContext::new();
72 assert!(ctx.runtime().is_none());
73 }
74
75 #[test]
76 fn producer_context_default_is_empty() {
77 let ctx = ProducerContext::default();
78 assert!(ctx.runtime().is_none());
79 }
80
81 #[test]
82 fn producer_context_with_runtime_sets_handle() {
83 let runtime: Arc<dyn RuntimeHandle> = Arc::new(NoopRuntime);
84 let ctx = ProducerContext::new().with_runtime(runtime.clone());
85
86 let attached = ctx.runtime().expect("runtime should be set");
87 assert!(Arc::ptr_eq(attached, &runtime));
88 }
89
90 #[test]
91 fn producer_context_clone_keeps_same_runtime_handle() {
92 let runtime: Arc<dyn RuntimeHandle> = Arc::new(NoopRuntime);
93 let ctx = ProducerContext::new().with_runtime(runtime.clone());
94 let cloned = ctx.clone();
95
96 assert!(Arc::ptr_eq(cloned.runtime().unwrap(), &runtime));
97 }
98
99 #[test]
100 fn producer_context_with_runtime_can_execute_command() {
101 let runtime: Arc<dyn RuntimeHandle> = Arc::new(NoopRuntime);
102 let ctx = ProducerContext::new().with_runtime(runtime);
103 let result = block_on(ctx.runtime().unwrap().execute(RuntimeCommand::StartRoute {
104 route_id: "r1".into(),
105 command_id: "c1".into(),
106 causation_id: None,
107 }))
108 .unwrap();
109
110 assert_eq!(result, RuntimeCommandResult::Accepted);
111 }
112
113 #[test]
114 fn producer_context_with_runtime_can_execute_query() {
115 let runtime: Arc<dyn RuntimeHandle> = Arc::new(NoopRuntime);
116 let ctx = ProducerContext::new().with_runtime(runtime);
117 let result = block_on(ctx.runtime().unwrap().ask(RuntimeQuery::ListRoutes)).unwrap();
118
119 assert_eq!(result, RuntimeQueryResult::Routes { route_ids: vec![] });
120 }
121
122 #[test]
123 fn producer_context_with_runtime_replaces_previous_runtime() {
124 let first: Arc<dyn RuntimeHandle> = Arc::new(NoopRuntime);
125 let second: Arc<dyn RuntimeHandle> = Arc::new(NoopRuntime);
126 let ctx = ProducerContext::new()
127 .with_runtime(first)
128 .with_runtime(second.clone());
129
130 assert!(Arc::ptr_eq(ctx.runtime().unwrap(), &second));
131 }
132}