1use std::{
19 any::Any,
20 cell::RefCell,
21 fmt::Debug,
22 rc::Rc,
23 sync::{
24 Arc,
25 atomic::{AtomicU64, Ordering},
26 },
27};
28
29use nautilus_common::{
30 clock::Clock,
31 msgbus::{
32 MStr, ShareableMessageHandler, TypedHandler, subscribe_account_state, subscribe_any,
33 subscribe_bars, subscribe_book_deltas, subscribe_book_depth as subscribe_book_depths,
34 subscribe_funding_rates, subscribe_greeks, subscribe_index_prices, subscribe_instruments,
35 subscribe_mark_prices, subscribe_option_greeks, subscribe_order_events,
36 subscribe_position_events, subscribe_quotes, subscribe_trades, unsubscribe_account_state,
37 unsubscribe_any, unsubscribe_bars, unsubscribe_book_deltas,
38 unsubscribe_book_depth as unsubscribe_book_depths, unsubscribe_funding_rates,
39 unsubscribe_greeks, unsubscribe_index_prices, unsubscribe_instruments,
40 unsubscribe_mark_prices, unsubscribe_option_greeks, unsubscribe_order_events,
41 unsubscribe_position_events, unsubscribe_quotes, unsubscribe_trades,
42 },
43};
44use nautilus_model::{
45 data::{
46 Bar, CustomData, FundingRateUpdate, IndexPriceUpdate, MarkPriceUpdate, OptionGreeks,
47 OrderBookDeltas, OrderBookDepth, QuoteTick, TradeTick, greeks::GreeksData,
48 },
49 events::{AccountState, OrderEventAny, PositionEvent},
50 instruments::{Instrument, InstrumentAny},
51};
52
53use super::traits::StreamingDataSink;
54
55type ClockBridge = Option<(Rc<RefCell<dyn Clock>>, Arc<AtomicU64>)>;
56
57pub struct StreamingSinkSubscription {
59 sink: Rc<RefCell<StreamingDataSink>>,
60 clock_bridge: ClockBridge,
61 any_handler: ShareableMessageHandler,
62 quotes_handler: TypedHandler<QuoteTick>,
63 trades_handler: TypedHandler<TradeTick>,
64 bars_handler: TypedHandler<Bar>,
65 deltas_handler: TypedHandler<OrderBookDeltas>,
66 depths_handler: TypedHandler<OrderBookDepth>,
67 mark_prices_handler: TypedHandler<MarkPriceUpdate>,
68 index_prices_handler: TypedHandler<IndexPriceUpdate>,
69 funding_rates_handler: TypedHandler<FundingRateUpdate>,
70 option_greeks_handler: TypedHandler<OptionGreeks>,
71 greeks_handler: TypedHandler<GreeksData>,
72 instruments_handler: TypedHandler<InstrumentAny>,
73 account_state_handler: TypedHandler<AccountState>,
74 order_events_handler: TypedHandler<OrderEventAny>,
75 position_events_handler: TypedHandler<PositionEvent>,
76}
77
78impl Debug for StreamingSinkSubscription {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 f.debug_struct(stringify!(StreamingSinkSubscription))
81 .finish_non_exhaustive()
82 }
83}
84
85impl StreamingSinkSubscription {
86 pub fn subscribe(sink: Rc<RefCell<StreamingDataSink>>, clock_bridge: ClockBridge) -> Self {
88 Self::subscribe_named(sink, clock_bridge, "streaming writer".to_string())
89 }
90
91 pub fn subscribe_named(
93 sink: Rc<RefCell<StreamingDataSink>>,
94 clock_bridge: ClockBridge,
95 name: String,
96 ) -> Self {
97 let name: Rc<str> = Rc::from(name);
98 let any_handler = any_handler(Rc::clone(&sink), clock_bridge.clone(), name.clone());
99 let quotes_handler =
100 typed_handler::<QuoteTick>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
101 let trades_handler =
102 typed_handler::<TradeTick>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
103 let bars_handler =
104 typed_handler::<Bar>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
105 let deltas_handler =
106 typed_handler::<OrderBookDeltas>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
107 let depths_handler =
108 typed_handler::<OrderBookDepth>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
109 let mark_prices_handler =
110 typed_handler::<MarkPriceUpdate>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
111 let index_prices_handler =
112 typed_handler::<IndexPriceUpdate>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
113 let funding_rates_handler = typed_handler::<FundingRateUpdate>(
114 Rc::clone(&sink),
115 clock_bridge.clone(),
116 name.clone(),
117 );
118 let option_greeks_handler =
119 typed_handler::<OptionGreeks>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
120 let greeks_handler =
121 typed_handler::<GreeksData>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
122 let instruments_handler =
123 typed_handler::<InstrumentAny>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
124 let account_state_handler =
125 typed_handler::<AccountState>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
126 let order_events_handler =
127 typed_handler::<OrderEventAny>(Rc::clone(&sink), clock_bridge.clone(), name.clone());
128 let position_events_handler =
129 typed_handler::<PositionEvent>(Rc::clone(&sink), clock_bridge.clone(), name);
130 let pattern = MStr::pattern("*");
131 let order_events_pattern = MStr::pattern("events.order.*");
135
136 subscribe_any(pattern, any_handler.clone(), None);
137 subscribe_quotes(pattern, quotes_handler.clone(), None);
138 subscribe_trades(pattern, trades_handler.clone(), None);
139 subscribe_bars(pattern, bars_handler.clone(), None);
140 subscribe_book_deltas(pattern, deltas_handler.clone(), None);
141 subscribe_book_depths(pattern, depths_handler.clone(), None);
142 subscribe_mark_prices(pattern, mark_prices_handler.clone(), None);
143 subscribe_index_prices(pattern, index_prices_handler.clone(), None);
144 subscribe_funding_rates(pattern, funding_rates_handler.clone(), None);
145 subscribe_option_greeks(pattern, option_greeks_handler.clone(), None);
146 subscribe_greeks(pattern, greeks_handler.clone(), None);
147 subscribe_instruments(pattern, instruments_handler.clone(), None);
148 subscribe_account_state(pattern, account_state_handler.clone(), None);
149 subscribe_order_events(order_events_pattern, order_events_handler.clone(), None);
150 subscribe_position_events(pattern, position_events_handler.clone(), None);
151
152 Self {
153 sink,
154 clock_bridge,
155 any_handler,
156 quotes_handler,
157 trades_handler,
158 bars_handler,
159 deltas_handler,
160 depths_handler,
161 mark_prices_handler,
162 index_prices_handler,
163 funding_rates_handler,
164 option_greeks_handler,
165 greeks_handler,
166 instruments_handler,
167 account_state_handler,
168 order_events_handler,
169 position_events_handler,
170 }
171 }
172
173 pub fn flush(&self) -> anyhow::Result<()> {
179 refresh_writer_clock(&self.clock_bridge);
180 self.sink.borrow_mut().flush()
181 }
182
183 pub fn close(&self) -> anyhow::Result<()> {
188 self.unsubscribe();
189 refresh_writer_clock(&self.clock_bridge);
190 self.sink.borrow_mut().close()
191 }
192
193 pub fn unsubscribe(&self) {
195 let pattern = MStr::pattern("*");
196 let order_events_pattern = MStr::pattern("events.order.*");
197
198 unsubscribe_any(pattern, &self.any_handler);
199 unsubscribe_quotes(pattern, &self.quotes_handler);
200 unsubscribe_trades(pattern, &self.trades_handler);
201 unsubscribe_bars(pattern, &self.bars_handler);
202 unsubscribe_book_deltas(pattern, &self.deltas_handler);
203 unsubscribe_book_depths(pattern, &self.depths_handler);
204 unsubscribe_mark_prices(pattern, &self.mark_prices_handler);
205 unsubscribe_index_prices(pattern, &self.index_prices_handler);
206 unsubscribe_funding_rates(pattern, &self.funding_rates_handler);
207 unsubscribe_option_greeks(pattern, &self.option_greeks_handler);
208 unsubscribe_greeks(pattern, &self.greeks_handler);
209 unsubscribe_instruments(pattern, &self.instruments_handler);
210 unsubscribe_account_state(pattern, &self.account_state_handler);
211 unsubscribe_order_events(order_events_pattern, &self.order_events_handler);
212 unsubscribe_position_events(pattern, &self.position_events_handler);
213 }
214}
215
216fn typed_handler<T: 'static>(
217 sink: Rc<RefCell<StreamingDataSink>>,
218 clock_bridge: ClockBridge,
219 name: Rc<str>,
220) -> TypedHandler<T> {
221 TypedHandler::from(move |message: &T| {
222 write_bus_message(&sink, &clock_bridge, &name, message);
223 })
224}
225
226fn any_handler(
227 sink: Rc<RefCell<StreamingDataSink>>,
228 clock_bridge: ClockBridge,
229 name: Rc<str>,
230) -> ShareableMessageHandler {
231 ShareableMessageHandler::from_any(move |message: &dyn Any| {
232 write_bus_message(&sink, &clock_bridge, &name, message);
233 })
234}
235
236fn write_bus_message(
237 sink: &Rc<RefCell<StreamingDataSink>>,
238 clock_bridge: &ClockBridge,
239 name: &str,
240 message: &dyn Any,
241) {
242 refresh_writer_clock(clock_bridge);
243
244 if let Err(e) = sink.borrow_mut().write_any(message) {
245 log::warn!(
246 "Failed to write {name} {} message: {e}",
247 streaming_message_label(message)
248 );
249 }
250}
251
252fn refresh_writer_clock(clock_bridge: &ClockBridge) {
253 if let Some((clock, shared)) = clock_bridge {
254 shared.store(clock.borrow().timestamp_ns().as_u64(), Ordering::Relaxed);
255 }
256}
257
258fn streaming_message_label(message: &dyn Any) -> String {
259 if let Some(custom) = message.downcast_ref::<CustomData>() {
260 return format!(
261 "CustomData({}, identifier={:?})",
262 custom.data.type_name(),
263 custom.data_type.identifier()
264 );
265 }
266
267 if let Some(instrument) = message.downcast_ref::<InstrumentAny>() {
268 return format!("InstrumentAny({})", instrument.id());
269 }
270
271 if let Some(bar) = message.downcast_ref::<Bar>() {
272 return format!("Bar({})", bar.bar_type);
273 }
274
275 if let Some(quotes) = message.downcast_ref::<QuoteTick>() {
276 return format!("QuoteTick({})", quotes.instrument_id);
277 }
278
279 if let Some(trade) = message.downcast_ref::<TradeTick>() {
280 return format!("TradeTick({})", trade.instrument_id);
281 }
282
283 "unknown".to_string()
284}