Skip to main content

StaticDataCache

Struct StaticDataCache 

Source
pub struct StaticDataCache {
    pub securities: DashMap<String, CachedSecurityInfo>,
    pub id_to_key: DashMap<u64, String>,
    pub trade_dates: DashMap<String, Vec<CachedTradeDate>>,
    pub plates: DashMap<String, Vec<CachedPlateInfo>>,
    pub owner_to_warrants: RwLock<HashMap<u64, HashSet<u64>>>,
    pub stale_mkt_ids: DashMap<String, ()>,
    pub mkt_id_refresh_marked_total: AtomicU64,
    pub mkt_id_refresh_done_total: AtomicU64,
    pub mkt_id_refresh_failed_total: AtomicU64,
    /* private fields */
}
Expand description

静态数据缓存

Fields§

§securities: DashMap<String, CachedSecurityInfo>

股票静态信息: “market_code” → info

v1.4.106 codex 1148 F9: 对外 read-only。生产代码不应直接 .insert() 这个 DashMap (会导致 id_to_key / owner_to_warrants 三索引不一致), 必须走 upsert_full_security_info / upsert_basic_security_info / delete_security_info 统一写入口。pub 仅为 backwards-compat: 既有迭代 caller (snapshot.rs for-iter .iter()) 仍能 read-only 遍历。

§id_to_key: DashMap<u64, String>

stock_id → “market_code” key (反向映射,用于推送时查找)

v1.4.106 codex 1148 F9: 对外 read-only (同 securities)。

§trade_dates: DashMap<String, Vec<CachedTradeDate>>

交易日: “market:year-month” → Vec

§plates: DashMap<String, Vec<CachedPlateInfo>>

板块: “market:plate_type” → Vec

§owner_to_warrants: RwLock<HashMap<u64, HashSet<u64>>>

窝轮正股 owner_id → 该正股对应的所有窝轮 stock_id 集合

v1.4.106 codex 1148 F6: value 从 Vec<u64> 改为 HashSet<u64> 防 重复 (SQLite reload + stock-list re-sync 同 warrant 多次 push 不会再重复). stock-list delete_flag反向索引清理: 旧 owner 下移除旧 warrant (delete_security_info 内部维护), update 时也维护。

§stale_mkt_ids: DashMap<String, ()>

v1.4.89 P2-A: 需要 mkt_id refresh 的 cache key 集合.

Callers get_security_info_trigger_refresh 在返 info 前检查 info.needs_mkt_id_refresh(), 是则 mark key 到这里. 背景 worker (gateway bridge) 定期 drain_stale_mkt_ids() 批量 CMD 20106 refresh.

用 DashMap<String, ()> 替代 HashSet 免 lock 竞争.

§mkt_id_refresh_marked_total: AtomicU64

v1.4.89 P2-A: mkt_id refresh 统计计数, 用于 metrics 观察.

  • mkt_id_refresh_marked_total: 累积 mark stale 次数
  • mkt_id_refresh_done_total: 累积 backend CMD 20106 成功 refresh 次数
  • mkt_id_refresh_failed_total: 累积 refresh failure 次数
§mkt_id_refresh_done_total: AtomicU64§mkt_id_refresh_failed_total: AtomicU64

Implementations§

Source§

impl StaticDataCache

Source

pub fn new() -> Self

Source

pub fn get_security_info_trigger_refresh( &self, key: &str, ) -> Option<CachedSecurityInfo>

v1.4.89 P2-A: 取 cache info 同时机会性 mark stale (若 mkt_id=0).

返 Some(info) 如果 cache hit (无论是否 stale). 返 None 如果 miss.

info.needs_mkt_id_refresh() 判 stale → mark stale_mkt_ids, bump mkt_id_refresh_marked_total counter. 用 DashMap::insert 幂等 (同 key 重入不 double mark 但会 bump counter — 可接受).

替代 get_security_info 的推荐路径; 老 method 保留作 lookup-only 接口.

Source

pub fn mark_stale_mkt_id(&self, key: &str)

v1.4.89 P2-A: 显式 mark key 需要 mkt_id refresh.

幂等: 同 key 可重入. Counter mkt_id_refresh_marked_total 每次都 bump (用作 metrics 观察 heuristic fallback 触发频率).

Source

pub fn drain_stale_mkt_ids(&self) -> Vec<String>

v1.4.89 P2-A: drain 所有 stale keys, 清空集合, 返 Vec (给 backend worker 批量 CMD 20106 refresh).

背景 worker 用法 (伪码):

loop {
    sleep(Duration::from_secs(60)).await;
    let stale = cache.drain_stale_mkt_ids();
    if stale.is_empty() { continue; }
    for chunk in stale.chunks(50) {
        // CMD 20106 SecuritiesReq for chunk
        // on success: cache.update_mkt_id(key, new_mkt_id)
        //              + cache.record_mkt_id_refresh_done()
        // on failure: cache.record_mkt_id_refresh_failed()
    }
}
Source

pub fn update_mkt_id(&self, key: &str, new_mkt_id: u32) -> bool

v1.4.89 P2-A: 更新已 cache row 的 mkt_id (refresh success 时调).

只改 mkt_id 字段, 其他字段保留 (info 可能有 SQLite 里更精准的 lot_size / list_time 等). 若 key 不在 cache (已被 evict), no-op.

Source

pub fn record_mkt_id_refresh_failed(&self)

v1.4.89 P2-A: 记录 refresh failure (不改 cache row, 让下次 drain 重试).

Source

pub fn stale_mkt_ids_count(&self) -> usize

v1.4.89 P2-A: 当前 stale keys 数 (给 observability / debug).

Source

pub fn upsert_full_security_info(&self, key: &str, info: CachedSecurityInfo)

v1.4.106 codex 1148 F9 (P3): 统一写入口 — 完整静态行 (StockListFull / Bootstrap source)。同步维护 securities + id_to_key + 若有 owner 还更新 owner_to_warrants自动 dedup: 已有同 key 但 warrnt_stock_owner 变化时, 旧 owner 下移除该 warrant id, 新 owner 下添加。

替代生产代码里手动调 securities.insert() + id_to_key.insert() + add_warrant_owner() 三步骤的 pattern。

不允许 caller 把不完整的 source 标 StockListFull(若 info.source == OnDemandBasic, 用 upsert_basic_security_info 而非本 fn)。

Source

pub fn upsert_crypto_pair_info(&self, key: &str, pair: CryptoPairInfo)

写入 stock-list 下发的 crypto 货币对元数据。

Source

pub fn get_crypto_pair_info(&self, key: &str) -> Option<CryptoPairInfo>

读取 crypto 货币对元数据。

Source

pub fn set_crypto_trade_configs_for_broker( &self, broker_id: u32, configs: Vec<CryptoTradeConfig>, )

用 backend CMD20102 拉回的配置替换某个 broker 的 crypto trade config。

Source

pub fn get_crypto_trade_config( &self, broker_id: u32, symbol: &str, exchange: &str, ) -> Option<CryptoTradeConfig>

查询某个 crypto symbol 的交易配置。

Source

pub fn upsert_basic_security_info(&self, key: &str, info: CachedSecurityInfo)

v1.4.106 codex 1148 F9 (P3): 统一写入口 — 部分静态行 (OnDemandBasic source)。同步维护 securities + id_to_key, 不动 owner_to_warrants (因为 OnDemandBasic 不含 warrnt_stock_owner 字段, value 必为 0)。

info.source 必须是 OnDemandBasic (debug_assert)。

Source

pub fn delete_security_info(&self, stock_id: u64) -> bool

v1.4.106 codex 1148 F9 (P3): 删除 cache row + 同步清三个索引 (securities, id_to_key, owner_to_warrants)。

用于 stock-list delete_flag = true 场景。 返 true 如果 row 存在并被删除, false 如果 stock_id 不在 id_to_key

查询某个 backend push stock_id 对应的主连/连续合约 sec_key 别名。

只返回 stock-list 明确下发 origin_id / zhuli_id 关系的 key;不做 HSImain 等字符串启发式。调用方通常先按 id_to_key 处理真实合约, 再把这里返回的 main-link key 一并投递。

Source

pub fn quote_push_targets_for_stock_id( &self, stock_id: u64, ) -> Vec<(String, CachedSecurityInfo)>

查询 backend push stock_id 的所有 quote 投递目标。

顺序保持为:真实 stock_id 对应 key(如有)优先,然后是 stock-list origin_id / zhuli_id 下发的主连/连续合约别名 key。调用方不再直接 读取 id_to_keyfuture_main_link_aliases 两个索引,避免 alias 逻辑 分散在 push parser 里。

Source

pub fn quote_push_targets_for_stock_key( &self, stock_id: u64, broker_id: Option<NonZeroU32>, ) -> Vec<(QotSecurityKey, CachedSecurityInfo)>

v1.4.110 Phase 2 Slice 5: broker-aware 推送投递目标查询.

对应 push parser 从 SecurityQuote.broker_id 重建 broker-aware QotStockKey 的路径 (对齐 C++ NNBiz_Qot_PushQot.cpp:220-269).

语义:

  • broker_id = None (C++ m_hasBroker=false): 只查 no-broker key, 返 QotSecurityKey::no_broker(public_sec_key, stock_id)quote_push_targets_for_stock_id 等价
  • broker_id = Some(N) (C++ m_hasBroker=true): 沿 stock_id 反向 找到 public_sec_key, 再用 QotSecurityKey::from_broker_id(...) 构造 broker-aware key. 该 broker 下 cache 写入独立桶 "market_code@b{N}", 不污染同 stock_id 其他 broker 的 cache.

Phase 2 默认: backend 当前对普通股 push 仍不下发 broker_id (=None), 与升级前行为完全等价. crypto multi-broker push 会带 broker_id, Phase 3 reader caller (handler GetBasicQot 等) 替换走 _broker 版本后, broker-aware cache 才被消费.

Source

pub fn set_security_info(&self, key: &str, info: CachedSecurityInfo)

👎Deprecated since 1.4.106: use upsert_full_security_info / upsert_basic_security_info / delete_security_info

deprecated: 改用 upsert_full_security_info / upsert_basic_security_info 维护三索引一致性。本 method 仅写 securities, 更新 id_to_key / owner_to_warrants — 直接调 会产生半索引行 (按 code 查得到, 按 stock_id 反向查不到)。

v1.4.106 codex 1148 F9 起仅保留作 unit test / bench 兼容。生产代码 禁用 (review-time grep set_security_info 须 0 命中 in crates/futu-*/src/)。

Source

pub fn get_security_info(&self, key: &str) -> Option<CachedSecurityInfo>

Source

pub fn get_security_info_by_stock_id( &self, stock_id: u64, ) -> Option<CachedSecurityInfo>

通过 stock_id 查找股票信息 (使用 id_to_key 反向映射)

Source

pub fn add_warrant_owner(&self, warrant_stock_id: u64, owner_stock_id: u64)

添加窝轮→正股的映射关系

v1.4.106 codex 1148 F6: HashSet 自动去重, 重复 add 同 (warrant, owner) 是 idempotent — SQLite reload + stock-list sync 不会重复入。

Source

pub fn search_warrants_by_owner(&self, owner_stock_id: u64) -> Vec<u64>

通过正股 ID 搜索该正股的所有窝轮

v1.4.106 codex 1148 F6: 内部 HashSet, 返 Vec (call site backward compatible)。返序非确定 (HashSet 不保留 insertion order); call site 若 需要稳定序应自己 sort。

Trait Implementations§

Source§

impl Default for StaticDataCache

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more