nautilus_common/msgbus/
stubs.rs1use std::{
17 any::Any,
18 cell::RefCell,
19 rc::Rc,
20 sync::{
21 Arc,
22 atomic::{AtomicBool, Ordering},
23 },
24};
25
26use ahash::AHashMap;
27use nautilus_core::UUID4;
28use ustr::Ustr;
29
30use crate::{
31 messages::data::{DataResponse, DataResponseEnvelope},
32 msgbus::{
33 Handler, IntoHandler, ShareableMessageHandler, TypedHandler, TypedIntoHandler,
34 typed_handler::shareable_handler,
35 },
36};
37
38#[derive(Debug, Clone)]
40pub struct StubMessage;
41
42#[derive(Debug, Clone)]
44pub struct StubMessageHandler {
45 id: Ustr,
46}
47
48impl Handler<dyn Any> for StubMessageHandler {
49 fn id(&self) -> Ustr {
50 self.id
51 }
52
53 fn handle(&self, _message: &dyn Any) {}
54}
55
56#[must_use]
57pub fn get_stub_shareable_handler(id: Option<Ustr>) -> ShareableMessageHandler {
58 let unique_id = id.unwrap_or_else(|| Ustr::from(UUID4::new().as_str()));
59 shareable_handler(Rc::new(StubMessageHandler { id: unique_id }))
60}
61
62#[derive(Debug, Clone)]
64pub struct CallCheckHandler {
65 id: Ustr,
66 called: Arc<AtomicBool>,
67}
68
69impl CallCheckHandler {
70 #[must_use]
71 pub fn new(id: Option<Ustr>) -> Self {
72 let unique_id = id.unwrap_or_else(|| Ustr::from(UUID4::new().as_str()));
73 Self {
74 id: unique_id,
75 called: Arc::new(AtomicBool::new(false)),
76 }
77 }
78
79 #[must_use]
80 pub fn was_called(&self) -> bool {
81 self.called.load(Ordering::SeqCst)
82 }
83
84 #[must_use]
86 pub fn handler(&self) -> ShareableMessageHandler {
87 shareable_handler(Rc::new(self.clone()))
88 }
89}
90
91impl Handler<dyn Any> for CallCheckHandler {
92 fn id(&self) -> Ustr {
93 self.id
94 }
95
96 fn handle(&self, _message: &dyn Any) {
97 self.called.store(true, Ordering::SeqCst);
98 }
99}
100
101#[must_use]
104pub fn get_call_check_handler(id: Option<Ustr>) -> (ShareableMessageHandler, CallCheckHandler) {
105 let checker = CallCheckHandler::new(id);
106 let handler = checker.handler();
107 (handler, checker)
108}
109
110#[derive(Debug, Clone)]
112pub struct AnySavingHandler<T> {
113 id: Ustr,
114 messages: Rc<RefCell<Vec<T>>>,
115}
116
117impl<T: Clone + 'static> AnySavingHandler<T> {
118 #[must_use]
119 pub fn new(id: Option<Ustr>) -> Self {
120 let unique_id = id.unwrap_or_else(|| Ustr::from(UUID4::new().as_str()));
121 Self {
122 id: unique_id,
123 messages: Rc::new(RefCell::new(Vec::new())),
124 }
125 }
126
127 #[must_use]
128 pub fn get_messages(&self) -> Vec<T> {
129 self.messages.borrow().clone()
130 }
131
132 pub fn clear(&self) {
133 self.messages.borrow_mut().clear();
134 }
135
136 #[must_use]
138 pub fn handler(&self) -> ShareableMessageHandler {
139 shareable_handler(Rc::new(self.clone()))
140 }
141}
142
143impl<T: Clone + 'static> Handler<dyn Any> for AnySavingHandler<T> {
144 fn id(&self) -> Ustr {
145 self.id
146 }
147
148 fn handle(&self, message: &dyn Any) {
149 if let Some(m) = message.downcast_ref::<T>() {
150 self.messages.borrow_mut().push(m.clone());
151 } else {
152 log::error!(
153 "AnySavingHandler: expected {} got {:?}",
154 std::any::type_name::<T>(),
155 message.type_id()
156 );
157 }
158 }
159}
160
161#[must_use]
164pub fn get_any_saving_handler<T: Clone + 'static>(
165 id: Option<Ustr>,
166) -> (ShareableMessageHandler, AnySavingHandler<T>) {
167 let saver = AnySavingHandler::new(id);
168 let handler = saver.handler();
169 (handler, saver)
170}
171
172pub type MessageSavingHandler<T> = AnySavingHandler<T>;
174
175#[must_use]
177pub fn get_response_saving_handler<T: Clone + 'static>(
178 id: Option<Ustr>,
179) -> (TypedHandler<DataResponseEnvelope>, AnySavingHandler<T>) {
180 let (payload_handler, saver) = get_any_saving_handler::<T>(id);
181
182 let handler = TypedHandler::from(move |envelope: &DataResponseEnvelope| {
183 if !envelope.completed() {
184 return;
185 }
186
187 let Some(response) = envelope.response() else {
188 return;
189 };
190
191 match response {
192 DataResponse::Data(r) => payload_handler.0.handle(r),
193 DataResponse::Instrument(r) => payload_handler.0.handle(r.as_ref()),
194 DataResponse::Instruments(r) => payload_handler.0.handle(r),
195 DataResponse::Book(r) => payload_handler.0.handle(r),
196 DataResponse::BookDeltas(r) => payload_handler.0.handle(r),
197 DataResponse::BookDepth(r) => payload_handler.0.handle(r),
198 DataResponse::Quotes(r) => payload_handler.0.handle(r),
199 DataResponse::Trades(r) => payload_handler.0.handle(r),
200 DataResponse::FundingRates(r) => payload_handler.0.handle(r),
201 DataResponse::OptionChainReferencePrice(r) => payload_handler.0.handle(r),
202 DataResponse::Bars(r) => payload_handler.0.handle(r),
203 }
204 });
205
206 (handler, saver)
207}
208
209#[derive(Debug, Clone)]
211pub struct TypedMessageSavingHandler<T> {
212 id: Ustr,
213 messages: Rc<RefCell<Vec<T>>>,
214}
215
216impl<T: Clone + 'static> TypedMessageSavingHandler<T> {
217 #[must_use]
218 pub fn new(id: Option<Ustr>) -> Self {
219 let unique_id = id.unwrap_or_else(|| Ustr::from(UUID4::new().as_str()));
220 Self {
221 id: unique_id,
222 messages: Rc::new(RefCell::new(Vec::new())),
223 }
224 }
225
226 #[must_use]
227 pub fn get_messages(&self) -> Vec<T> {
228 self.messages.borrow().clone()
229 }
230
231 #[must_use]
233 pub fn handler(&self) -> TypedHandler<T> {
234 TypedHandler::new(self.clone())
235 }
236}
237
238impl<T: Clone + 'static> Handler<T> for TypedMessageSavingHandler<T> {
239 fn id(&self) -> Ustr {
240 self.id
241 }
242
243 fn handle(&self, message: &T) {
244 self.messages.borrow_mut().push(message.clone());
245 }
246}
247
248#[must_use]
251pub fn get_typed_message_saving_handler<T: Clone + 'static>(
252 id: Option<Ustr>,
253) -> (TypedHandler<T>, TypedMessageSavingHandler<T>) {
254 let saving_handler = TypedMessageSavingHandler::new(id);
255 let typed_handler = saving_handler.handler();
256 (typed_handler, saving_handler)
257}
258
259#[derive(Debug, Clone)]
264pub struct TypedIntoMessageSavingHandler<T> {
265 id: Ustr,
266 messages: Rc<RefCell<Vec<T>>>,
267}
268
269impl<T: 'static> TypedIntoMessageSavingHandler<T> {
270 #[must_use]
271 pub fn new(id: Option<Ustr>) -> Self {
272 let unique_id = id.unwrap_or_else(|| Ustr::from(UUID4::new().as_str()));
273 Self {
274 id: unique_id,
275 messages: Rc::new(RefCell::new(Vec::new())),
276 }
277 }
278
279 #[must_use]
281 pub fn new_with_messages(id: Option<Ustr>, messages: Rc<RefCell<Vec<T>>>) -> Self {
282 let unique_id = id.unwrap_or_else(|| Ustr::from(UUID4::new().as_str()));
283 Self {
284 id: unique_id,
285 messages,
286 }
287 }
288
289 #[must_use]
290 pub fn get_messages(&self) -> Vec<T>
291 where
292 T: Clone,
293 {
294 self.messages.borrow().clone()
295 }
296
297 #[must_use]
299 pub fn handler(&self) -> TypedIntoHandler<T> {
300 TypedIntoHandler::new(Self {
301 id: self.id,
302 messages: self.messages.clone(),
303 })
304 }
305
306 pub fn clear(&self) {
307 self.messages.borrow_mut().clear();
308 }
309}
310
311impl<T: 'static> IntoHandler<T> for TypedIntoMessageSavingHandler<T> {
312 fn id(&self) -> Ustr {
313 self.id
314 }
315
316 fn handle(&self, message: T) {
317 self.messages.borrow_mut().push(message);
318 }
319}
320
321#[must_use]
324pub fn get_typed_into_message_saving_handler<T: 'static>(
325 id: Option<Ustr>,
326) -> (TypedIntoHandler<T>, TypedIntoMessageSavingHandler<T>) {
327 let saving_handler = TypedIntoMessageSavingHandler::new(id);
328 let typed_handler = saving_handler.handler();
329 (typed_handler, saving_handler)
330}
331
332thread_local! {
336 static SAVING_HANDLERS: RefCell<AHashMap<Ustr, Box<dyn std::any::Any>>> = RefCell::new(AHashMap::new());
337}
338
339#[must_use]
341pub fn get_message_saving_handler<T: Clone + 'static>(id: Option<Ustr>) -> ShareableMessageHandler {
342 let (handler, saver) = get_any_saving_handler::<T>(id);
343 let handler_id = handler.0.id();
344 SAVING_HANDLERS.with(|handlers| {
345 handlers.borrow_mut().insert(handler_id, Box::new(saver));
346 });
347 handler
348}
349
350#[must_use]
352pub fn get_saved_messages<T: Clone + 'static>(handler: &ShareableMessageHandler) -> Vec<T> {
353 let handler_id = handler.0.id();
354 SAVING_HANDLERS.with(|handlers| {
355 let handlers = handlers.borrow();
356 if let Some(saver) = handlers.get(&handler_id)
357 && let Some(saver) = saver.downcast_ref::<AnySavingHandler<T>>()
358 {
359 return saver.get_messages();
360 }
361 Vec::new()
362 })
363}