futu_cache/trd_cache/
order_broker.rs1use super::*;
2use futu_domain_trade_account::{
3 OrderBrokerActiveOrderFacts, OrderBrokerPruneAction, OrderBrokerPruneFacts,
4 OrderBrokerRecordAction, OrderBrokerRecordFacts, OrderBrokerRehomeAction,
5 OrderBrokerRehomeFacts, plan_order_broker_prune_action, plan_order_broker_record_action,
6 plan_order_broker_rehome_action,
7};
8
9impl TrdCache {
10 pub fn record_order_broker(
11 &self,
12 acc_id: AccKey,
13 order_id_ex: impl AsRef<str>,
14 broker_id: u32,
15 ) {
16 let OrderBrokerRecordAction::Record {
17 normalized_order_id_ex,
18 } = plan_order_broker_record_action(OrderBrokerRecordFacts {
19 order_id_ex: order_id_ex.as_ref(),
20 })
21 else {
22 return;
23 };
24 let order_id_ex = normalized_order_id_ex.to_string();
25 let previous_acc = self
26 .order_broker_accounts
27 .insert(order_id_ex.clone(), acc_id);
28 if let OrderBrokerRehomeAction::RemoveOldAccIndex { old_acc_id } =
29 plan_order_broker_rehome_action(OrderBrokerRehomeFacts {
30 previous_acc,
31 new_acc: acc_id,
32 })
33 {
34 self.remove_order_broker_id_from_acc_index(old_acc_id, &order_id_ex);
35 }
36 self.order_broker_ids_by_acc
37 .entry(acc_id)
38 .or_default()
39 .insert(order_id_ex.clone());
40 self.order_brokers.insert(order_id_ex, broker_id);
41 }
42
43 fn remove_order_broker_id_from_acc_index(&self, acc_id: AccKey, order_id_ex: &str) {
44 let mut remove_bucket = false;
45 if let Some(mut ids) = self.order_broker_ids_by_acc.get_mut(&acc_id) {
46 ids.remove(order_id_ex);
47 remove_bucket = ids.is_empty();
48 }
49 if remove_bucket {
50 self.order_broker_ids_by_acc
51 .remove_if(&acc_id, |_, ids| ids.is_empty());
52 }
53 }
54
55 pub(super) fn prune_order_brokers_for_acc(&self, acc_id: AccKey) {
56 if self.order_brokers.is_empty() {
57 return;
58 }
59
60 let prune_actions = {
61 let orders = self.orders.get(&acc_id);
62 let active_orders = orders
63 .as_ref()
64 .map(|entry| {
65 entry
66 .value()
67 .iter()
68 .map(|order| OrderBrokerActiveOrderFacts {
69 order_id_ex: &order.order_id_ex,
70 backend_order_id: &order.backend_order_id,
71 })
72 .collect::<Vec<_>>()
73 })
74 .unwrap_or_default();
75
76 let Some(order_ids) = self.order_broker_ids_by_acc.get(&acc_id) else {
77 return;
78 };
79 order_ids
80 .iter()
81 .map(|order_id_ex| {
82 let mapping_owner_is_changed_acc = self
83 .order_broker_accounts
84 .get(order_id_ex.as_str())
85 .is_some_and(|entry| *entry.value() == acc_id);
86 let action = plan_order_broker_prune_action(OrderBrokerPruneFacts {
87 broker_order_id_ex: order_id_ex,
88 mapping_owner_is_changed_acc,
89 active_orders: &active_orders,
90 });
91 (order_id_ex.clone(), action)
92 })
93 .filter(|(_, action)| *action != OrderBrokerPruneAction::Keep)
94 .collect::<Vec<_>>()
95 };
96
97 for (order_id_ex, action) in prune_actions {
98 match action {
99 OrderBrokerPruneAction::Keep => {}
100 OrderBrokerPruneAction::RemoveBrokerMappingAndAccIndex => {
101 self.order_broker_accounts.remove(&order_id_ex);
102 self.order_brokers.remove(&order_id_ex);
103 self.remove_order_broker_id_from_acc_index(acc_id, &order_id_ex);
104 }
105 OrderBrokerPruneAction::RemoveAccIndexOnly => {
106 self.remove_order_broker_id_from_acc_index(acc_id, &order_id_ex);
107 }
108 }
109 }
110 }
111}