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