futu_cache/
market_event.rs1use std::collections::BTreeSet;
2
3use dashmap::DashMap;
4use futu_domain_qot_market_state::{
5 MarketEventUpdate, MarketStateSnapshot, MarketTradeDateSnapshot, TradeDateUpdatePlan,
6 merge_market_state_patch, plan_market_trade_date_update,
7};
8
9#[derive(Clone, Debug, Default, PartialEq, Eq)]
10pub struct MarketEventApplyOutcome {
11 pub market_state_updates: usize,
12 pub trade_date_updates: usize,
13 pub changed_trade_date_quote_markets: Vec<u8>,
14}
15
16#[derive(Default)]
17pub struct MarketEventCache {
18 market_states: DashMap<u32, MarketStateSnapshot>,
19 market_trade_dates: DashMap<u32, MarketTradeDateSnapshot>,
20}
21
22impl MarketEventCache {
23 #[must_use]
24 pub fn new() -> Self {
25 Self::default()
26 }
27
28 pub fn apply_batch(&self, updates: &[MarketEventUpdate]) -> MarketEventApplyOutcome {
29 let mut outcome = MarketEventApplyOutcome::default();
30 let mut changed_quote_markets = BTreeSet::new();
31
32 for update in updates {
33 match update {
34 MarketEventUpdate::MarketState(patch) => {
35 let existing = self
36 .market_states
37 .get(&patch.market_id)
38 .map(|row| row.clone());
39 let merged = merge_market_state_patch(existing.as_ref(), patch.clone());
40 self.market_states.insert(merged.market_id, merged);
41 outcome.market_state_updates += 1;
42 }
43 MarketEventUpdate::MarketTradeDate(update) => {
44 let existing = self
45 .market_trade_dates
46 .get(&update.market_id)
47 .map(|row| row.clone());
48 if let TradeDateUpdatePlan::Changed(snapshot) =
49 plan_market_trade_date_update(existing.as_ref(), update.clone())
50 {
51 if snapshot.quote_market_type != 0 {
55 changed_quote_markets.insert(snapshot.quote_market_type);
56 }
57 self.market_trade_dates.insert(snapshot.market_id, snapshot);
58 outcome.trade_date_updates += 1;
59 }
60 }
61 }
62 }
63
64 outcome.changed_trade_date_quote_markets = changed_quote_markets.into_iter().collect();
65 outcome
66 }
67
68 #[must_use]
69 pub fn market_state(&self, market_id: u32) -> Option<MarketStateSnapshot> {
70 self.market_states.get(&market_id).map(|row| row.clone())
71 }
72
73 #[must_use]
74 pub fn market_states(&self) -> Vec<MarketStateSnapshot> {
75 let mut rows: Vec<_> = self.market_states.iter().map(|row| row.clone()).collect();
76 rows.sort_by_key(|row| row.market_id);
77 rows
78 }
79
80 #[must_use]
81 pub fn market_trade_date(&self, market_id: u32) -> Option<MarketTradeDateSnapshot> {
82 self.market_trade_dates
83 .get(&market_id)
84 .map(|row| row.clone())
85 }
86}