nautilus_common/msgbus/
mod.rs1mod api;
40mod backing;
41pub mod config;
42pub mod core;
43pub mod matching;
44pub mod message;
45pub mod mstr;
46pub mod stubs;
47pub mod switchboard;
48pub mod typed_endpoints;
49pub mod typed_handler;
50pub mod typed_router;
51
52pub(crate) mod external;
53
54use std::{
55 any::Any,
56 cell::{Cell, RefCell},
57 rc::Rc,
58};
59
60use nautilus_core::UUID4;
61#[cfg(feature = "defi")]
62use nautilus_model::defi::{Block, Pool, PoolFeeCollect, PoolFlash, PoolLiquidityUpdate, PoolSwap};
63use nautilus_model::{
64 data::{
65 Bar, FundingRateUpdate, GreeksData, IndexPriceUpdate, MarkPriceUpdate, OrderBookDeltas,
66 OrderBookDepth10, QuoteTick, TradeTick,
67 option_chain::{OptionChainSlice, OptionGreeks},
68 },
69 events::{AccountState, OrderEventAny, PortfolioSnapshot, PositionEvent},
70 instruments::InstrumentAny,
71 orderbook::OrderBook,
72};
73use smallvec::SmallVec;
74
75#[cfg(feature = "live")]
76pub use self::backing::{
77 MessageBusExternalIngress, MessageBusExternalReceiver, external_io_from_backing,
78};
79pub use self::{
80 api::*,
81 backing::{
82 MessageBusBacking, MessageBusBackingFactory, MessageBusExternalEgress,
83 external_egress_from_backing,
84 },
85 config::MessageBusConfig,
86 core::{MessageBus, Subscription},
87 message::{BusMessage, BusPayloadCategory, BusPayloadType},
88 mstr::{Endpoint, MStr, Pattern, Topic},
89 switchboard::MessagingSwitchboard,
90 typed_endpoints::{EndpointMap, IntoEndpointMap},
91 typed_handler::{
92 CallbackHandler, Handler, IntoHandler, ShareableMessageHandler, TypedHandler,
93 TypedIntoHandler,
94 },
95 typed_router::{TopicRouter, TypedSubscription},
96};
97use crate::timer::TimeEvent;
98
99pub(super) const HANDLER_BUFFER_CAP: usize = 64;
101
102thread_local! {
111 pub(super) static MESSAGE_BUS: RefCell<Option<Rc<RefCell<MessageBus>>>> = const { RefCell::new(None) };
112 pub(super) static HAS_EXTERNAL_EGRESS: Cell<bool> = const { Cell::new(false) };
113 pub(super) static SUPPRESS_EXTERNAL_DEPTH: Cell<u32> = const { Cell::new(0) };
114
115 pub(super) static ANY_HANDLERS: RefCell<SmallVec<[ShareableMessageHandler; HANDLER_BUFFER_CAP]>> =
116 RefCell::new(SmallVec::new());
117
118 pub(super) static DELTAS_HANDLERS: RefCell<SmallVec<[TypedHandler<OrderBookDeltas>; HANDLER_BUFFER_CAP]>> =
119 RefCell::new(SmallVec::new());
120 pub(super) static DEPTH10_HANDLERS: RefCell<SmallVec<[TypedHandler<OrderBookDepth10>; HANDLER_BUFFER_CAP]>> =
121 RefCell::new(SmallVec::new());
122 pub(super) static BOOK_HANDLERS: RefCell<SmallVec<[TypedHandler<OrderBook>; HANDLER_BUFFER_CAP]>> =
123 RefCell::new(SmallVec::new());
124 pub(super) static QUOTE_HANDLERS: RefCell<SmallVec<[TypedHandler<QuoteTick>; HANDLER_BUFFER_CAP]>> =
125 RefCell::new(SmallVec::new());
126 pub(super) static TRADE_HANDLERS: RefCell<SmallVec<[TypedHandler<TradeTick>; HANDLER_BUFFER_CAP]>> =
127 RefCell::new(SmallVec::new());
128 pub(super) static BAR_HANDLERS: RefCell<SmallVec<[TypedHandler<Bar>; HANDLER_BUFFER_CAP]>> =
129 RefCell::new(SmallVec::new());
130 pub(super) static MARK_PRICE_HANDLERS: RefCell<SmallVec<[TypedHandler<MarkPriceUpdate>; HANDLER_BUFFER_CAP]>> =
131 RefCell::new(SmallVec::new());
132 pub(super) static INDEX_PRICE_HANDLERS: RefCell<SmallVec<[TypedHandler<IndexPriceUpdate>; HANDLER_BUFFER_CAP]>> =
133 RefCell::new(SmallVec::new());
134 pub(super) static FUNDING_RATE_HANDLERS: RefCell<SmallVec<[TypedHandler<FundingRateUpdate>; HANDLER_BUFFER_CAP]>> =
135 RefCell::new(SmallVec::new());
136 pub(super) static GREEKS_HANDLERS: RefCell<SmallVec<[TypedHandler<GreeksData>; HANDLER_BUFFER_CAP]>> =
137 RefCell::new(SmallVec::new());
138 pub(super) static OPTION_GREEKS_HANDLERS: RefCell<SmallVec<[TypedHandler<OptionGreeks>; HANDLER_BUFFER_CAP]>> =
139 RefCell::new(SmallVec::new());
140 pub(super) static OPTION_CHAIN_HANDLERS: RefCell<SmallVec<[TypedHandler<OptionChainSlice>; HANDLER_BUFFER_CAP]>> =
141 RefCell::new(SmallVec::new());
142 pub(super) static ACCOUNT_STATE_HANDLERS: RefCell<SmallVec<[TypedHandler<AccountState>; HANDLER_BUFFER_CAP]>> =
143 RefCell::new(SmallVec::new());
144 pub(super) static PORTFOLIO_SNAPSHOT_HANDLERS: RefCell<SmallVec<[TypedHandler<PortfolioSnapshot>; HANDLER_BUFFER_CAP]>> =
145 RefCell::new(SmallVec::new());
146 pub(super) static ORDER_EVENT_HANDLERS: RefCell<SmallVec<[TypedHandler<OrderEventAny>; HANDLER_BUFFER_CAP]>> =
147 RefCell::new(SmallVec::new());
148 pub(super) static POSITION_EVENT_HANDLERS: RefCell<SmallVec<[TypedHandler<PositionEvent>; HANDLER_BUFFER_CAP]>> =
149 RefCell::new(SmallVec::new());
150 pub(super) static INSTRUMENT_HANDLERS: RefCell<SmallVec<[TypedHandler<InstrumentAny>; HANDLER_BUFFER_CAP]>> =
151 RefCell::new(SmallVec::new());
152
153 #[cfg(feature = "defi")]
154 pub(super) static DEFI_BLOCK_HANDLERS: RefCell<SmallVec<[TypedHandler<Block>; HANDLER_BUFFER_CAP]>> =
155 RefCell::new(SmallVec::new());
156 #[cfg(feature = "defi")]
157 pub(super) static DEFI_POOL_HANDLERS: RefCell<SmallVec<[TypedHandler<Pool>; HANDLER_BUFFER_CAP]>> =
158 RefCell::new(SmallVec::new());
159 #[cfg(feature = "defi")]
160 pub(super) static DEFI_SWAP_HANDLERS: RefCell<SmallVec<[TypedHandler<PoolSwap>; HANDLER_BUFFER_CAP]>> =
161 RefCell::new(SmallVec::new());
162 #[cfg(feature = "defi")]
163 pub(super) static DEFI_LIQUIDITY_HANDLERS: RefCell<SmallVec<[TypedHandler<PoolLiquidityUpdate>; HANDLER_BUFFER_CAP]>> =
164 RefCell::new(SmallVec::new());
165 #[cfg(feature = "defi")]
166 pub(super) static DEFI_COLLECT_HANDLERS: RefCell<SmallVec<[TypedHandler<PoolFeeCollect>; HANDLER_BUFFER_CAP]>> =
167 RefCell::new(SmallVec::new());
168 #[cfg(feature = "defi")]
169 pub(super) static DEFI_FLASH_HANDLERS: RefCell<SmallVec<[TypedHandler<PoolFlash>; HANDLER_BUFFER_CAP]>> =
170 RefCell::new(SmallVec::new());
171}
172
173#[derive(Debug)]
175pub struct SuppressExternalGuard;
176
177impl SuppressExternalGuard {
178 #[must_use]
179 pub fn new() -> Self {
180 SUPPRESS_EXTERNAL_DEPTH.with(|depth| depth.set(depth.get().saturating_add(1)));
181 Self
182 }
183}
184
185impl Default for SuppressExternalGuard {
186 fn default() -> Self {
187 Self::new()
188 }
189}
190
191impl Drop for SuppressExternalGuard {
192 fn drop(&mut self) {
193 SUPPRESS_EXTERNAL_DEPTH.with(|depth| depth.set(depth.get().saturating_sub(1)));
194 }
195}
196
197pub fn set_message_bus(msgbus: Rc<RefCell<MessageBus>>) {
199 HAS_EXTERNAL_EGRESS.with(|flag| flag.set(msgbus.borrow().has_external_egress()));
200 MESSAGE_BUS.with(|bus| {
201 *bus.borrow_mut() = Some(msgbus);
202 });
203}
204
205pub fn get_message_bus() -> Rc<RefCell<MessageBus>> {
209 MESSAGE_BUS.with(|bus| {
210 let mut slot = bus.borrow_mut();
211 let rc = slot.get_or_insert_with(|| Rc::new(RefCell::new(MessageBus::default())));
212 rc.clone()
213 })
214}
215
216pub fn try_get_message_bus() -> Option<Rc<RefCell<MessageBus>>> {
218 MESSAGE_BUS.with(|bus| bus.borrow().clone())
219}
220
221pub trait BusTap: 'static {
230 fn on_publish(&self, topic: MStr<Topic>, message: &dyn Any);
232
233 fn on_send(&self, endpoint: MStr<Endpoint>, message: &dyn Any);
235
236 fn on_response(&self, _correlation_id: &UUID4, _message: &dyn Any) {}
238}
239
240thread_local! {
241 pub(super) static BUS_TAP: RefCell<Option<Rc<dyn BusTap>>> = const { RefCell::new(None) };
242}
243
244pub fn set_bus_tap(tap: Rc<dyn BusTap>) {
250 BUS_TAP.with(|slot| {
251 *slot.borrow_mut() = Some(tap);
252 });
253}
254
255pub fn clear_bus_tap() {
259 BUS_TAP.with(|slot| {
260 *slot.borrow_mut() = None;
261 });
262}
263
264#[inline]
265pub(super) fn dispatch_tap_publish(topic: MStr<Topic>, message: &dyn Any) {
266 let tap = BUS_TAP.with(|slot| slot.borrow().clone());
270 if let Some(tap) = tap {
271 tap.on_publish(topic, message);
272 }
273}
274
275#[inline]
276pub(super) fn dispatch_tap_send(endpoint: MStr<Endpoint>, message: &dyn Any) {
277 let tap = BUS_TAP.with(|slot| slot.borrow().clone());
278 if let Some(tap) = tap {
279 tap.on_send(endpoint, message);
280 }
281}
282
283#[inline]
284pub(super) fn dispatch_tap_response(correlation_id: &UUID4, message: &dyn Any) {
285 let tap = BUS_TAP.with(|slot| slot.borrow().clone());
286 if let Some(tap) = tap {
287 tap.on_response(correlation_id, message);
288 }
289}
290
291#[inline]
292pub(crate) fn dispatch_tap_time_event(event: &TimeEvent) {
293 dispatch_tap_publish(MessagingSwitchboard::time_event_topic(), event);
294}