pub struct TrdCache {
pub accounts: DashMap<AccKey, CachedTrdAcc>,
pub account_relations: DashMap<AccKey, Vec<AccKey>>,
pub public_account_ids: DashMap<AccKey, ()>,
pub funds: DashMap<FundsCacheKey, StampedTradeSnapshot<CachedFunds>>,
pub positions: DashMap<PositionsCacheKey, StampedTradeSnapshot<Vec<CachedPosition>>>,
pub combo_positions: DashMap<PositionsCacheKey, StampedTradeSnapshot<Vec<CachedPosition>>>,
pub orders: DashMap<AccKey, Vec<CachedOrder>>,
pub order_fills: DashMap<AccKey, Vec<CachedOrderFill>>,
pub order_brokers: DashMap<String, u32>,
pub order_op_req_orders: DashMap<OrderOpReqKey, String>,
pub cipher_state_versions: DashMap<AccKey, Arc<AtomicU64>>,
pub pending_order_confirms: DashMap<OrderConfirmKey, OrderConfirmContext>,
/* private fields */
}Expand description
交易数据缓存
Fields§
§accounts: DashMap<AccKey, CachedTrdAcc>C++ NNData_Trd_AccList::m_mapUserAccList equivalent.
This is the authoritative internal account index used by request
validation, broker routing, and funds/positions/order queries. It may
contain universal parent accounts that are excluded from the public
Trd_GetAccList projection.
account_relations: DashMap<AccKey, Vec<AccKey>>C++ NNData_Trd_AccList::m_mapIDRelation equivalent:
universal_or_self_acc_id -> public sub account ids.
Trd_GetAccList uses this relation via get_accounts() to expose the
same public projection as C++ GetAllSubAccList, while lookup_account
and direct accounts.get() still see the full internal map.
public_account_ids: DashMap<AccKey, ()>Public account ids derived from account_relations.
funds: DashMap<FundsCacheKey, StampedTradeSnapshot<CachedFunds>>资金: FundsCacheKey { acc_id, asset_category, currency } → funds.
v1.4.106 Finding A: 之前 DashMap<AccKey, CachedFunds> 一 acc 一 snapshot,
Universal/Futures 多币种场景被覆盖 — 改 currency-aware key 对齐 C++
m_mapAccFund: NN_AssetKey -> NN_TrdCurrency -> Ndt_Trd_AccFund.
positions: DashMap<PositionsCacheKey, StampedTradeSnapshot<Vec<CachedPosition>>>持仓: PositionsCacheKey { acc_id, asset_category, currency } → Vec
combo_positions: DashMap<PositionsCacheKey, StampedTradeSnapshot<Vec<CachedPosition>>>组合持仓视图: PositionsCacheKey { acc_id, asset_category, currency=None }
→ Vec
C++ keeps ordinary and combo views in separate stores
(SetPositionList vs SetComboPositionList) and optionStrategyView
chooses which one to read. Keeping the caches separate prevents a combo
refresh from overwriting ordinary position-list output.
orders: DashMap<AccKey, Vec<CachedOrder>>当日订单: acc_id → Vec
order_fills: DashMap<AccKey, Vec<CachedOrderFill>>当日成交: acc_id → Vec
C++ INNData_Trd_Deal stores direct/query deal rows and suppresses
unchanged status notifications through NeedUpdateDeal.
order_brokers: DashMap<String, u32>v1.4.48 #1: 订单 broker 映射(order_id_ex → broker_id_used)
起源:v1.4.47 P0.1 修了 PlaceOrder 按 sec_market 选 broker,但 ModifyOrder /
CancelOrder 仍按 account.security_firm 选 broker,导致“在 broker 1007 (US)
下的单,cancel 去 broker 1019 (CA) 拒“ 的 cross-broker 故障。
修法:PlaceOrder 成功后把 (order_id_ex, broker_id_used) 缓存到这里。
ModifyOrder / CancelOrder 拿到 c2s.order_id_ex 后先查 broker_id;
命中 → 路由到同 broker;未命中 → fallback account.firm 路由。
订单快照更新后会按当前缓存订单 GC stale entry,避免 daemon 长跑时每单
一个 string key 永久累积。
注:cipher 按 sub-account acc_id 存储(ciphers map)。对照 C++
NNData_Trd_AccList::m_mapAccCipher:不同 broker 的账户天然有不同
nAccID,存储已隔离(v1.4.49 清理了 v1.4.48 cipher_brokers workaround,
该字段在 v1.4.48 #11 routing 对齐 C++ 后成 dead code)。
order_op_req_orders: DashMap<OrderOpReqKey, String>C++ NNProto_Trd_OnPush::m_mapReqIDOrderID equivalent:
backend write MsgHeader.req_id -> backend order_id.
C++ stores this after successful place/modify/cancel ACK and consumes it
when NOTICE_TYPE_ORDER_OP_RESULT only carries order_op_req_ids. It is
a best-effort helper for an extra order-detail refresh, not the primary
order state source.
cipher_state_versions: DashMap<AccKey, Arc<AtomicU64>>v1.4.73 A2 BUG-008 fix: per-account cipher state version counter。
外部 tester (v1.4.71) AI 报告 5 步 repro:
Step 1: unlock pwd → cache EXECUTED (idem_key=unlock-xxx)
Step 2: 同 body → cache HIT (正常幂等)
Step 3: EMPTY {} LOCK → v1.4.39 cipher 清
Step 4: 同 body → cache HIT 返 stale 成功! (真 bug)
Step 5: place-order → -401 "交易未解锁"v1.4.72 Option C(空 body 不写 cache)只防 step 3 污染,未修 step 4 stale。
Option A 真修:unlock idem_key 构造时纳入当前 cipher_state_version,
lock 清 cipher 时 fetch_add(1, SeqCst) → version 递增 → step 4 同 body
得 idem_key 不同(version=0 → version=1)→ cache miss → 真执行 unlock
或 backend 校验失败返清晰错误。
为啥 SeqCst:unlock_trade handler 可能并发,确保 version 递增对所有
后续 idem_key 构造 visible(ciphers.remove() + fetch_add() 顺序严格)。
注:version 不持久化 —— daemon restart 重新从 0 开始,等效于“新 cache“, 之前的 idem entries 也被 cache TTL 清光,零冲突。
pending_order_confirms: DashMap<OrderConfirmKey, OrderConfirmContext>v1.4.106 codex 0226 F1+F2: pending OrderConfirm context per
(acc_id, ftapi_order_id).
PlaceOrder ack 响应里若 OrderNewRsp.action.type == ORDER_CONFIRM=5 且
action.order_confirm.is_some(), daemon 必须 capture
CltActionOrderConfirm 字段, 用于后续 Trd_ReconfirmOrder 处理时构造
backend OrderConfirmReq (cmd 4728).
生命周期:
- PlaceOrder ack 路径: capture 后
insert(key, ctx) - ReconfirmOrder handler: lookup → 构造 backend req → 收到
OrderConfirmRspresult==0后remove(key)(一次性消费, 防止重复 confirm) - TTL: 5min (
ORDER_CONFIRM_CONTEXT_TTL_MS),now - inserted_at_ms检查; stale entry handler 拒绝 + GC 清理 - daemon restart 全清 (内存 cache, backend 重新发 PlaceOrder 即可获新 context)
详见 OrderConfirmContext doc.
Implementations§
Source§impl TrdCache
impl TrdCache
Sourcepub fn merge_preserving_stubs(
&self,
acc_id: u64,
backend_orders: Vec<CachedOrder>,
)
pub fn merge_preserving_stubs( &self, acc_id: u64, backend_orders: Vec<CachedOrder>, )
v1.4.90 cache saga fix: merge backend authoritative orders while retaining fresh local stubs.
Sourcepub fn merge_preserving_stubs_with_now(
&self,
acc_id: u64,
backend_orders: Vec<CachedOrder>,
now_ms: u64,
)
pub fn merge_preserving_stubs_with_now( &self, acc_id: u64, backend_orders: Vec<CachedOrder>, now_ms: u64, )
Injectable-clock variant used by regression tests for fresh/stale stub boundaries.
Sourcepub fn replace_order_snapshot_like_cpp(
&self,
acc_id: u64,
backend_orders: &[CachedOrder],
) -> OrderSnapshotReplacementPlan
pub fn replace_order_snapshot_like_cpp( &self, acc_id: u64, backend_orders: &[CachedOrder], ) -> OrderSnapshotReplacementPlan
Atomically plan C++ UpdateOrderList notifications and replace the
backend-authoritative snapshot while retaining Rust local compatibility
rows (fresh optimistic stubs and C++ local Deleted rows).
Sourcepub fn replace_order_snapshot_like_cpp_with_now(
&self,
acc_id: u64,
backend_orders: &[CachedOrder],
now_ms: u64,
) -> OrderSnapshotReplacementPlan
pub fn replace_order_snapshot_like_cpp_with_now( &self, acc_id: u64, backend_orders: &[CachedOrder], now_ms: u64, ) -> OrderSnapshotReplacementPlan
Injectable-clock variant used by local-stub boundary tests.
Source§impl TrdCache
impl TrdCache
pub fn get_cipher(&self, acc_id: AccKey) -> Option<Vec<u8>>
Sourcepub fn set_cipher(&self, acc_id: AccKey, cipher: Vec<u8>)
pub fn set_cipher(&self, acc_id: AccKey, cipher: Vec<u8>)
Publish a newly unlocked cipher and invalidate every in-flight CMD2902 lease for this account by incrementing its revision.
pub fn get_cipher_revision(&self, acc_id: AccKey) -> u64
pub fn cipher_count(&self) -> usize
Sourcepub fn clear_cipher(&self, acc_id: AccKey) -> bool
pub fn clear_cipher(&self, acc_id: AccKey) -> bool
Clear one account cipher while retaining a revision tombstone.
pub fn clear_all_ciphers_and_bump_versions(&self) -> (usize, Vec<(u64, u64)>)
Sourcepub fn begin_cipher_exchange(
&self,
broker_id: u32,
connection_epoch: u64,
) -> CipherExchangeLease
pub fn begin_cipher_exchange( &self, broker_id: u32, connection_epoch: u64, ) -> CipherExchangeLease
Freeze the exact real-account cipher set for one broker connection. C++ sorts the broker account list before building CMD2902; Rust preserves deterministic account order for the same wire behavior.
Sourcepub fn complete_cipher_exchange(
&self,
lease: &CipherExchangeLease,
response: Vec<(AccKey, Vec<u8>)>,
) -> Result<CipherExchangePublishReport, CipherExchangeError>
pub fn complete_cipher_exchange( &self, lease: &CipherExchangeLease, response: Vec<(AccKey, Vec<u8>)>, ) -> Result<CipherExchangePublishReport, CipherExchangeError>
Complete CMD2902 only after validating an exact, duplicate-free, non-empty response set. Each account publish is then guarded by the captured revision + broker + connection epoch + request id CAS tuple.
Sourcepub fn fail_cipher_exchange(&self, lease: &CipherExchangeLease)
pub fn fail_cipher_exchange(&self, lease: &CipherExchangeLease)
Mark only the still-owned lease rows failed. A newer unlock/exchange is left untouched.
Sourcepub fn with_current_broker_cipher_generation<T>(
&self,
broker_id: u32,
expected_generation: u64,
publish: impl FnOnce() -> T,
) -> Option<T>
pub fn with_current_broker_cipher_generation<T>( &self, broker_id: u32, expected_generation: u64, publish: impl FnOnce() -> T, ) -> Option<T>
Run route publication only while the broker’s cipher generation still equals the completed/empty lease generation. Cipher set/clear/publish share this lock, closing the last-check-to-install race.
Sourcepub fn get_cipher_for_broker_epoch(
&self,
acc_id: AccKey,
broker_id: u32,
connection_epoch: u64,
) -> Option<Vec<u8>>
pub fn get_cipher_for_broker_epoch( &self, acc_id: AccKey, broker_id: u32, connection_epoch: u64, ) -> Option<Vec<u8>>
Financial write gate: pending/failed/stale-epoch ciphers are not usable. A newly unlocked cipher is initially unbound and remains usable until a reconnect lease explicitly transitions it to Pending.
Source§impl TrdCache
impl TrdCache
Sourcepub fn mark_asset_server_push(&self, acc_id: u64, asset_category: i32)
pub fn mark_asset_server_push(&self, acc_id: u64, asset_category: i32)
Record the C++ UpdateSvrPushTime(NN_AssetKey) equivalent.
Ref: NNData_Trd_Acc.cpp:416-420. Funds, positions and combo positions
under the same (acc_id, asset_category) compare against this watermark.
Source§impl TrdCache
impl TrdCache
Sourcepub fn set_jp_sub_account_types<I>(&self, entries: I)
pub fn set_jp_sub_account_types<I>(&self, entries: I)
Replace JP sub-account id/type mapping after an account-list refresh.
Sourcepub fn jp_acc_type_for_sub_account(
&self,
acc_id: AccKey,
sub_account_id: u64,
) -> Option<i32>
pub fn jp_acc_type_for_sub_account( &self, acc_id: AccKey, sub_account_id: u64, ) -> Option<i32>
Resolve backend order sub_account_id to public FTAPI jp_acc_type.
Account protocol documents JP cash as sub_account_id=0 and
SubAccountType=0, but account list does not send a cash sub-account
row. Preserve that convention when backend order rows explicitly carry
sub_account_id=0.
Sourcepub fn sub_account_for_jp_acc_type(
&self,
acc_id: AccKey,
jp_acc_type: i32,
) -> Option<u64>
pub fn sub_account_for_jp_acc_type( &self, acc_id: AccKey, jp_acc_type: i32, ) -> Option<u64>
Resolve public FTAPI jp_acc_type back to backend sub-account id.
C++ JP combo trade-write paths call
Ndt_Trd_AccItem::GetSubAccIDByType; this cache side index is populated
from the same account-list sub-account rows and is used only when a
backend request must carry pos_sub_account_id / sub_account_id.
pub fn jp_sub_account_type_entries_for_accounts( &self, acc_ids: &HashSet<AccKey>, ) -> Vec<(AccKey, u64, i32)>
Source§impl TrdCache
impl TrdCache
Sourcepub fn replace_order_fill_snapshot_like_cpp(
&self,
acc_id: u64,
incoming: Vec<CachedOrderFill>,
) -> FillSnapshotReplacementPlan
pub fn replace_order_fill_snapshot_like_cpp( &self, acc_id: u64, incoming: Vec<CachedOrderFill>, ) -> FillSnapshotReplacementPlan
Apply C++ UpdateDealList to a fully paged current-fill snapshot.
Planning and replacement share one DashMap entry guard so a direct fill push cannot observe or mutate a half-replaced snapshot.
Sourcepub fn upsert_order_fill(&self, acc_id: u64, fill: CachedOrderFill) -> bool
pub fn upsert_order_fill(&self, acc_id: u64, fill: CachedOrderFill) -> bool
Apply C++ UpdateAndNotifyOneDeal admission to the current fill cache.
Returns true only when callers should emit Trd_UpdateOrderFill.
Source§impl TrdCache
impl TrdCache
Sourcepub fn mark_order_deleted_local(
&self,
acc_id: u64,
order_id: u64,
order_id_ex: Option<&str>,
) -> bool
pub fn mark_order_deleted_local( &self, acc_id: u64, order_id: u64, order_id_ex: Option<&str>, ) -> bool
Mark an existing cached order as local Deleted(23) after a successful DeleteFailOrder operation.
C++ keeps local orders (bIsLocalOrder=true) across UpdateOrderList
backend refreshes. Rust must do the same for delete success, otherwise a
backend refresh that omits the just-deleted failed order makes
order_list_query() return empty while official C++ still shows
Deleted(23).
Sourcepub fn clear_pending_confirm_for_acc(&self, acc_id: u64) -> usize
pub fn clear_pending_confirm_for_acc(&self, acc_id: u64) -> usize
v1.4.105 BUG-v1.4.104-001 (P0): broker async confirm 到达后清 pending 标志.
当 push notice_type=4/5/8/100 (ORDER_UPDATE / ORDER_LIST_UPDATE /
TRADE_STATISTIC / ORDER_NTF) 到达对应 acc_id 时, 调本 fn 把所有
is_pending_broker_confirm=true 的 order 翻成 false.
设计选择: 不按 order_id 精确匹配清 — push notice 通常不带具体 order_id,
只表 “本 acc 有 order 状态变化”. 简化处理: acc 内任何 ORDER 类 push 到
即视为 broker 已开始处理本 acc 的 stub orders.
后续 query_orders refresh 会通过 merge_preserving_stubs 把 enriched
版本写入, 替换 stub.
返被清的 order 数 (caller 用于 audit log).
Sourcepub fn clear_pending_confirm_for_orders(
&self,
acc_id: u64,
order_ids: &[String],
) -> usize
pub fn clear_pending_confirm_for_orders( &self, acc_id: u64, order_ids: &[String], ) -> usize
v1.4.106 codex 0226 F4 (P2): selective clear pending confirm by order_ids.
clear_pending_confirm_for_acc 是 acc-level 全清, 但 ORDER push notify
在 backend 实际带具体 order_ids 时(notice_type=4 ORDER_UPDATE 通常
带), daemon 应只清对应订单的 pending flag, 而不是把同账户其他还没
confirm 的 stub 一并误清.
触发场景 (bridge/dispatcher.rs:251-268):
- notice_type=4/5/9 + 非空
order_ids(backend 真带 → 按订单清) - notice_type=4/5/9 + 空
order_ids→ fall back toclear_pending_confirm_for_acc
match 逻辑: o.backend_order_id / o.order_id_ex (alphanumeric backend
szOrderID) 与 order_ids 任一相等. 不 match o.order_id (FTAPI u64
hash) 因为 backend push 带的 order_ids 是 backend 原生 string id.
返被清的 order 数 (caller 用于 audit log).
Sourcepub fn purge_pending_stub_if_still_pending(
&self,
acc_id: u64,
order_id: u64,
) -> Option<String>
pub fn purge_pending_stub_if_still_pending( &self, acc_id: u64, order_id: u64, ) -> Option<String>
v1.4.105 BUG-v1.4.104-001 (P0): cleanup task 删超时未 confirm 的 pending stub.
触发: PlaceOrder spawn 一个 30s 延迟 task, 到点检查 (acc_id, order_id_ex)
对应的 stub 是否仍 is_stub=true && is_pending_broker_confirm=true.
若是 → 删 stub + warn (push channel 断 / broker 拒单未 push 的兜底).
不简单调 LOCAL_STUB_RETENTION_TTL_MS evict — 那个是 query_orders merge 时的逻辑, 这里是主动 GC pending stub. 两者互补.
返 (purged: bool, reason: 描述), caller 写 audit log.
Sourcepub fn scan_orphan_orders(
&self,
now_secs: f64,
threshold_secs: f64,
) -> Vec<OrphanOrder>
pub fn scan_orphan_orders( &self, now_secs: f64, threshold_secs: f64, ) -> Vec<OrphanOrder>
v1.4.83 §9 F6: 扫全 cache 查 orphan orders.
Orphan 定义: order_status ∈ {0, 1, 2, 4} (未达到 Submitted=5
之前的 in-flight stub) 且 create_timestamp.is_some() 且
now_secs - create_timestamp > threshold_secs.
含义对应 C++ proto OrderStatus enum (Trd_Common.proto:108):
- 0 = Unsubmitted (未提交) — 极端情况, daemon stub 修后不应该出现 (v1.4.103 P0 hotfix)
- 1 = WaitingSubmit (等待提交) — 条件单 stub 初值, 等触发
- 2 = Submitting (提交中) — 普通单 stub 初值 (v1.4.103 起)
- 4 = TimeOut (处理超时) — 后端回 timeout, 状态未知
为什么需要: v1.4.82 A2 PlaceOrder 成功后直接 upsert stub order
让 /api/orders 立刻可见 (BUG-60b0-002 fix). 后续 push notice_type=
4/5/8 / re-fetch 把 status 推到 5 (Submitted) / 10/11 (Filled).
若 push 通道断流 (§9 CMD3020 chain broken), stub 卡住 5min+ = orphan.
v1.4.103 P0 (BUG-WUZONG-001): stub status 从 0 (proto 定义为 Unsubmitted “未提交”, 触发客户端 retry 多下单) 改成 1/2 (WaitingSubmit/ Submitting, 对齐 C++ NNProto_Trd_OrderOp.cpp:483-510). orphan 检测同步 扩展到 {0, 1, 2, 4} 全 in-flight 状态 — 老 daemon 留下来 status=0 的 卡死 stub 也能被检测到.
返 Vec<OrphanOrder>; caller 决定 log 级别 + metric bump.
Source§impl TrdCache
impl TrdCache
Sourcepub fn get_cipher_state_version(&self, acc_id: u64) -> u64
pub fn get_cipher_state_version(&self, acc_id: u64) -> u64
v1.4.73 A2 BUG-008 fix: 读当前账户的 cipher state version(用于 unlock idem_key)。
首次访问 acc_id 会初始化为 0。后续每次 lock 清 cipher 会 fetch_add(1)。
idem_key 构造时把这个 version 纳入 hash → cipher 清后 version 递增 →
同 body 的 idem_key 不同 → cache miss → 真执行 unlock(或 backend 真校验)。
Sourcepub fn cipher_state_version_sum(&self) -> u64
pub fn cipher_state_version_sum(&self) -> u64
Conservative invalidation token for unlock-all idempotency keys.
Sourcepub fn bump_cipher_state_version(&self, acc_id: u64) -> u64
pub fn bump_cipher_state_version(&self, acc_id: u64) -> u64
v1.4.73 A2 BUG-008 fix: lock 清 cipher 时调,递增 version → 让下次 unlock 同 body 得 cache miss。
返回 new version(递增后值),便于调用方 log。
Sourcepub fn store_pending_order_confirm(
&self,
acc_id: u64,
ftapi_order_id: u64,
ctx: OrderConfirmContext,
now_ms: u64,
)
pub fn store_pending_order_confirm( &self, acc_id: u64, ftapi_order_id: u64, ctx: OrderConfirmContext, now_ms: u64, )
v1.4.106 codex 0226 F1+F2: PlaceOrder 解析到 OrderNewRsp.action.order_confirm
时调用, 保存上下文用于后续 Trd_ReconfirmOrder 构造 backend OrderConfirmReq.
now_ms 由 caller 传入 (便于单测注入固定时钟); 真实路径用
SystemTime::now().
Sourcepub fn get_pending_order_confirm(
&self,
acc_id: u64,
ftapi_order_id: u64,
now_ms: u64,
) -> Option<OrderConfirmContext>
pub fn get_pending_order_confirm( &self, acc_id: u64, ftapi_order_id: u64, now_ms: u64, ) -> Option<OrderConfirmContext>
v1.4.106 codex 0226 F1+F2: ReconfirmOrder handler 入口 lookup, 取出
(acc_id, ftapi_order_id) 对应 OrderConfirmContext.
返 None: cache miss (PlaceOrder 没存 / TTL 过期 / 已被消费). caller 必须
早 reject loud, 不允许 silent fallback (避免反模式 D / silent-success).
now_ms 检查 TTL: now - ctx.inserted_at_ms > ORDER_CONFIRM_CONTEXT_TTL_MS
视为 stale → return None + remove (proactive GC).
Sourcepub fn remove_pending_order_confirm(
&self,
acc_id: u64,
ftapi_order_id: u64,
) -> bool
pub fn remove_pending_order_confirm( &self, acc_id: u64, ftapi_order_id: u64, ) -> bool
v1.4.106 codex 0226 F1+F2: ReconfirmOrder backend 成功 (OrderConfirmRsp.result==0)
后调用, 从 cache 删除 (一次性消费, 防重复 confirm).
返 true 表示真有删除发生; false = 已被其他路径消费 / 过期 GC.
Sourcepub fn purge_stale_order_confirms(&self, now_ms: u64) -> usize
pub fn purge_stale_order_confirms(&self, now_ms: u64) -> usize
v1.4.106 codex 0226 F1+F2: GC stale OrderConfirmContext entries.
用于定时清理 (push dispatcher 收到 ORDER 类 push 时顺便扫一次), 防止 stale ctx 累积. 返回清理掉的条目数.
Sourcepub fn store_order_op_req_order(
&self,
acc_id: u64,
req_id: &str,
order_id_ex: &str,
) -> bool
pub fn store_order_op_req_order( &self, acc_id: u64, req_id: &str, order_id_ex: &str, ) -> bool
Store backend write req_id -> order_id_ex for C++ order op-result
push parity.
Ref:
NNProto_Trd_OnPush.cpp:22-27NNProto_Trd_OrderOpReal.cpp:217,352
Empty values are ignored because C++ only maps meaningful backend request/order pairs. Return value mirrors best-effort insert success.
Sourcepub fn take_order_id_by_op_req_id(
&self,
acc_id: u64,
req_id: &str,
) -> Option<String>
pub fn take_order_id_by_op_req_id( &self, acc_id: u64, req_id: &str, ) -> Option<String>
Consume backend order id by operation req_id.
C++ FindOrderIDByReqID erases the pair after lookup and clears the
helper map once it reaches 512 entries. Keep the same bounded,
best-effort behavior; a miss only means the push may have come from
another terminal/client and the dispatcher may fall back to full list.
Source§impl TrdCache
impl TrdCache
Sourcepub fn upsert_order(&self, acc_id: u64, order: CachedOrder) -> bool
pub fn upsert_order(&self, acc_id: u64, order: CachedOrder) -> bool
Update or insert a single order for push-driven order state.
Source§impl TrdCache
impl TrdCache
Sourcepub fn update_funds(&self, acc_id: u64, funds: CachedFunds)
pub fn update_funds(&self, acc_id: u64, funds: CachedFunds)
v1.4.106 Finding A (legacy compat): 不带 currency 维度的 update.
用 FundsCacheKey::legacy(acc_id) 作 key. 适用于:
- 现有 caller 还没改 signature 的 (背景: backend push 不一定知 currency)
- SingleCurrency / sim / Crypto / Forex 账户 (本来就单币种)
新 caller 应优先用 Self::update_funds_per_currency 显式标
currency 维度, 让 Universal/Futures 账户能存独立 snapshot per currency.
Sourcepub fn update_funds_per_currency(
&self,
acc_id: u64,
currency: Option<i32>,
funds: CachedFunds,
)
pub fn update_funds_per_currency( &self, acc_id: u64, currency: Option<i32>, funds: CachedFunds, )
v1.4.106 Finding A (preferred for Universal/Futures): 带 currency
维度的 update. backend push 时若知 funds 的实际 currency (从 f.currency
字段或 push context 派生), 应该用这个 helper 让多币种 snapshot 不互相覆盖.
对齐 C++ INNData_Trd_Acc::SetAccFund(stKey, enCurrency, ...).
Sourcepub fn update_funds_scoped(
&self,
acc_id: u64,
asset_category: i32,
currency: Option<i32>,
funds: CachedFunds,
)
pub fn update_funds_scoped( &self, acc_id: u64, asset_category: i32, currency: Option<i32>, funds: CachedFunds, )
Currency + asset-category aware funds update.
JP derivative accounts use asset_category as part of the C++ asset key.
Non-JP/legacy callers should pass asset_category=0, which preserves the
existing legacy/per-currency key shape.
Sourcepub fn update_funds_scoped_with_returned_currency(
&self,
acc_id: u64,
asset_category: i32,
requested_currency: Option<i32>,
funds: CachedFunds,
)
pub fn update_funds_scoped_with_returned_currency( &self, acc_id: u64, asset_category: i32, requested_currency: Option<i32>, funds: CachedFunds, )
Update the requested funds bucket and also mirror the returned backend currency bucket when it is known.
C++ stores Ndt_Trd_AccFund under accFund.enCurrency
(INNData_Trd_Acc.cpp::SetAccFund). A Rust caller may request CMD3020
with currency=None because the daemon derived the backend default, but
REST/CLI later read the same account through an explicit effective
currency bucket. Mirroring prevents an older per-currency snapshot from
masking a fresher default refresh.
Sourcepub fn get_funds(
&self,
acc_id: u64,
currency: Option<i32>,
) -> (Option<CachedFunds>, bool)
pub fn get_funds( &self, acc_id: u64, currency: Option<i32>, ) -> (Option<CachedFunds>, bool)
v1.4.106 Finding A: cache lookup with C++-equivalent fallback.
对齐 C++ INNData_Trd_Acc::GetAccFund(stKey, enCurrency, pAccFund):
先试 requested currency, 找不到则 fallback 到 latest/first available
currency, 返 false (caller 应看 boolean 决定是否 trust).
输入 currency:
Some(c): Universal/Futures 路径, 优先 match per-currency snapshotNone: SingleCurrency 路径, 直接 matchlegacy(acc_id)snapshot
输出 (funds, currency_match):
(Some(funds), true): 精确命中 requested currency snapshot(Some(funds), false): 命中 fallback (legacy 或不同 currency 的 snapshot — caller 应不要 silent trust, 至少 log warn 或 surface currency mismatch)(None, _): 完全 cache miss
Sourcepub fn get_funds_scoped(
&self,
acc_id: u64,
asset_category: i32,
currency: Option<i32>,
) -> (Option<CachedFunds>, bool)
pub fn get_funds_scoped( &self, acc_id: u64, asset_category: i32, currency: Option<i32>, ) -> (Option<CachedFunds>, bool)
Funds lookup using the same (acc_id, asset_category, currency) dimensions
as Self::update_funds_scoped.
For asset_category != 0 we require an exact scoped hit. Falling back to a
legacy or another asset-category snapshot would mix JP derivative asset
buckets and silently return the wrong funds.
pub fn get_funds_scoped_with_freshness( &self, acc_id: u64, asset_category: i32, currency: Option<i32>, ) -> FundsSnapshotLookup
pub fn update_positions(&self, acc_id: u64, positions: Vec<CachedPosition>)
pub fn update_positions_scoped( &self, acc_id: u64, asset_category: i32, positions: Vec<CachedPosition>, )
pub fn update_positions_currency_scoped( &self, acc_id: u64, asset_category: i32, currency: i32, positions: Vec<CachedPosition>, )
pub fn update_combo_positions_scoped( &self, acc_id: u64, asset_category: i32, positions: Vec<CachedPosition>, )
pub fn get_positions_scoped( &self, acc_id: u64, asset_category: i32, ) -> Option<Vec<CachedPosition>>
pub fn get_positions_currency_scoped( &self, acc_id: u64, asset_category: i32, currency: i32, ) -> Option<Vec<CachedPosition>>
pub fn get_combo_positions_scoped( &self, acc_id: u64, asset_category: i32, ) -> Option<Vec<CachedPosition>>
pub fn get_positions_scoped_with_freshness( &self, acc_id: u64, asset_category: i32, ) -> PositionsSnapshotLookup
pub fn get_positions_currency_scoped_with_freshness( &self, acc_id: u64, asset_category: i32, currency: i32, ) -> PositionsSnapshotLookup
pub fn get_combo_positions_scoped_with_freshness( &self, acc_id: u64, asset_category: i32, ) -> PositionsSnapshotLookup
pub fn has_positions_scoped(&self, acc_id: u64, asset_category: i32) -> bool
Sourcepub fn find_combo_position_item(
&self,
acc_id: u64,
position_id: u64,
) -> Option<CachedPosition>
pub fn find_combo_position_item( &self, acc_id: u64, position_id: u64, ) -> Option<CachedPosition>
C++ INNData_Trd_Acc::GetComboPositionItem(nAccID, Unknown, nPositionID).
Combo trade-write paths receive public FTAPI positionID (a hash). The
backend requires the original business_position_id string plus the
position’s long account/sub-account ids. Search the combo-position view
for the account and return the cached row instead of guessing.
Source§impl TrdCache
impl TrdCache
Sourcepub fn find_order_for_trade_write(
&self,
acc_id: u64,
order_id: u64,
order_id_ex: Option<&str>,
) -> Result<CachedOrderSnapshot, ResolveOrderError>
pub fn find_order_for_trade_write( &self, acc_id: u64, order_id: u64, order_id_ex: Option<&str>, ) -> Result<CachedOrderSnapshot, ResolveOrderError>
Resolve cached order context for trade-write (modify / cancel) handlers.
Aligns with C++ APIServer_Trd_ModifyOrder.cpp: prefer orderIDEx
(backend szOrderID), otherwise resolve the FTAPI order hash from the
current order cache. Cache miss is fail-closed so callers return a clear
“refresh orders or pass orderIDEx” error instead of treating the hash as
a backend order id.
Source§impl TrdCache
impl TrdCache
pub fn new() -> Self
pub fn set_accounts(&self, accounts: Vec<CachedTrdAcc>)
Sourcepub fn set_accounts_with_relations(
&self,
accounts: Vec<CachedTrdAcc>,
relations: Vec<(AccKey, Vec<AccKey>)>,
)
pub fn set_accounts_with_relations( &self, accounts: Vec<CachedTrdAcc>, relations: Vec<(AccKey, Vec<AccKey>)>, )
Atomically replace the internal account map and the public projection.
relations mirrors C++ m_mapIDRelation: standalone accounts map to
themselves, while universal parents map to their public sub accounts.
This lets GetAccList expose only C++ GetAllSubAccList output without
losing hidden parent accounts needed by GetAccItem-style request paths.
Sourcepub fn required_trade_login_broker_ids(&self) -> Arc<BTreeSet<u32>>
pub fn required_trade_login_broker_ids(&self) -> Arc<BTreeSet<u32>>
Return the complete immutable broker set required by C++
IsTradeConnLogin() for the latest committed account snapshot.
pub fn get_accounts(&self) -> Vec<CachedTrdAcc>
Sourcepub fn backend_native_account_id_or_public_low_bits(
&self,
acc_id: AccKey,
) -> u64
pub fn backend_native_account_id_or_public_low_bits( &self, acc_id: AccKey, ) -> u64
Resolve backend/mobile native account id for request bodies.
CachedTrdAcc::intra_acc_id is the authoritative backend-native id
from CMD2282. The public FTAPI acc_id low 32 bits are only the legacy
fallback for old cache entries/tests that do not carry intra_acc_id.
Sourcepub fn backend_native_account_id_for_existing_account(
&self,
acc_id: AccKey,
) -> Option<u64>
pub fn backend_native_account_id_for_existing_account( &self, acc_id: AccKey, ) -> Option<u64>
Resolve backend-native account id, but require the account to exist in cache.
Sourcepub fn lookup_account(&self, acc_id: u64) -> Option<CachedTrdAcc>
pub fn lookup_account(&self, acc_id: u64) -> Option<CachedTrdAcc>
v1.4.106 codex 0932 F2 [P1]: 单 acc_id O(1) 查询 (DashMap key 直查).
用途: push_builder 构造 Trd_UpdateOrder / Trd_UpdateOrderFill header
之前 resolve trd_env + trd_market. 对齐 C++
INNData_Trd_AllAccList::GetAccEnv(nAccID) / GetAccMkt(nAccID).
返 None = cache miss (账户不在交易 cache 中). caller 必须 loud
return 不 fallback (sentinel 0 让 client filter reject =
silent-success 反模式).
Sourcepub fn find_acc_ids_by_card_num(&self, input: &str) -> Vec<u64>
pub fn find_acc_ids_by_card_num(&self, input: &str) -> Vec<u64>
v1.4.103 (B10): card_num → acc_id resolution helper.
接受输入:
- 16 位完整 card_num (
"1001100100800000"): 完全匹配card_num字段. - 4 位末尾 suffix (
"7680"): 匹配card_num末 4 位 (App 显示格式).
返 Vec<u64> (matching acc_ids):
- 0 个 → cache 中无 match (caller 决定 warn / abort);
- 1 个 → unique resolution;
-
= 2 个 → ambiguous (caller 必须 reject + log 候选, 不能 silent 接受).
空字符串 / 非纯数字 / 长度非 4 / 非 16 → 返 empty Vec (不 panic). 这是为了让 caller 输入校验 + resolution 双责权: 调用方应该已经校验过格式.
pub fn update_orders(&self, acc_id: u64, orders: Vec<CachedOrder>)
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for TrdCache
impl !RefUnwindSafe for TrdCache
impl Send for TrdCache
impl Sync for TrdCache
impl Unpin for TrdCache
impl UnsafeUnpin for TrdCache
impl UnwindSafe for TrdCache
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more