Skip to main content

PushHealth

Struct PushHealth 

Source
pub struct PushHealth { /* private fields */ }
Expand description

v1.4.83 §9 F2-F6 推送通道健康追踪。

所有字段 atomic 无锁,安全跨 sync push callback / async dispatcher / async orphan scan task / REST handler 多个执行上下文。

关键约束

  • last_push_received_at_ms:自 daemon 启动后任意 push 收到就更新; 用作 staleness watermark(/api/push-subscriber-info F5 暴露)
  • consecutive_parse_errors:成功 push 清零;失败 += 1;触发 F3/F4
  • total_parse_errors:monotonic,用于 metrics rate 计算
  • circuit_breaker_tripped_ms:F4 tripped 时写入 Unix ms;dispatcher 在 now - tripped_ms < 30_000 时跳过 dispatch(30s cooldown)

Implementations§

Source§

impl PushHealth

Source

pub fn record_f2_exhausted(&self, acc_id: u32) -> bool

v1.4.90 P2-B: 调用时机 = F2 retry 4 次全失败 (retry_with_exp_backoffErr). 记录该 acc_id 的 exhausted 事件; 若 30 min 窗口内 >= 3 次 → trip circuit + return true (caller log warn 一次 + ++counter).

返 false = 未 trip (caller 只 log debug); 返 true = 刚 trip (caller log warn + ++ f2_circuit_tripped_total).

Source

pub fn is_f2_circuit_tripped(&self, acc_id: u32) -> bool

v1.4.90 P2-B: 调用时机 = dispatcher 准备给 acc_id 起 F2 retry 之前. 返 true → caller 应 skip 本次 retry (账户在 cooldown 内); 返 false → 正常 retry.

1h cooldown 过则自动 reset (清 tripped_at_ms + 清 exhaust window).

Source§

impl PushHealth

Source

pub fn new() -> Self

Source

pub fn record_push_success(&self)

调用时机:每次 push callback 成功 parse/dispatch。 更新 last_push_received_at_ms + clear consecutive_parse_errors

  • increment total_pushes_received.

若之前 circuit tripped 且 cooldown 过了 → auto-reset(F4 自动恢复路径)。

Source

pub fn record_qot_push_sub_type(&self, sub_type: i32)

Record a regular QOT push dispatch watermark by FTAPI SubType.

This intentionally lives beside, not inside, record_push_success(): the backend callback only knows CMD6212, while the dispatcher knows the decoded FTAPI sub_type. Direct first-push cache replays do not call this method because they are synthetic cache events, not backend stream freshness evidence.

Source

pub fn record_parse_error(&self) -> u32

调用时机:push parse 失败(proto decode / 字段缺 / 非法值)。 返回当前 consecutive_errors 值(caller 据此决定是否触发 F3/F4)。

Source

pub fn record_resubscribe(&self)

F3 re-subscribe 触发时调用,更新 counter + 时间戳 + clear 计数.

Source

pub fn record_resubscribe_partial(&self, missed_keys: u32)

v1.4.106 codex 0631 F4 [P2]: resubscribe 部分失败触发时调用. missed_keys = cache miss / unresolved sec_keys 数 (0 = 全部 resolve OK). dispatcher / health 检查器 据本字段判 push stream degraded.

Source

pub fn trip_circuit(&self)

F4 circuit breaker trip 触发时调用.

Source

pub fn is_circuit_tripped_now(&self) -> bool

F4 lightweight state read for threshold checks that must not trigger the cooldown auto-reset side effect in should_skip_dispatch().

Source

pub fn should_skip_dispatch(&self) -> bool

F4 check: dispatcher 每个 event 开头调,tripped 且 cooldown 内 → skip dispatch return true (跳过); tripped 但 cooldown 过 → auto-reset return false; 未 tripped → return false.

Source

pub fn record_orphan_scan(&self, orphan_count: u64)

F6 orphan scan 发现 N 个卡住订单时调(N > 0 才调).

Source

pub fn record_trade_requery_dropped( &self, reason: &'static str, notice_type: u32, ) -> u64

v1.4.106 codex 0932 F1: 调用时机 = push_tx.try_send(TradeReQuery { .. })Err(TrySendError::Full | Closed). 全部 silent drop 路径都改为 调用本方法 + bump counter + log warn 1 次.

reason = “queue_full” / “queue_closed”; notice_type = backend NotifyMsg.notice_type (4 / 6 / 100 / 101 / etc.)

返新的 dropped_total 值 — caller 可据此判定 “首次 drop 触发 warn” 但本实装由 caller 简单 log_warn (caller 已有 acc_id / order_ids context).

Source

pub fn is_healthy(&self) -> bool

F5 暴露给 /api/push-subscriber-info: 是否 push stream 健康.

规则:同时满足才判 healthy:

  • circuit 未 tripped
  • consecutive_parse_errors < 5
  • last_push_received_at_ms != 0 且 now - last < 60_000 (60s 内有 push) OR daemon 刚启动 < 60s(没 push 不等于不健康,可能还没订阅)
  • v1.4.106 codex 0932 F1: 60s 内 发生 TradeReQuery 队列丢弃 (队列满 = backpressure, 短期内 dispatcher 无法消费完, 上层应感知)
Source

pub fn compute_degraded_reason(&self) -> Option<String>

v1.4.106 codex 0631 F4 [P2]: 计算 degraded reason — 与 is_healthy() 同源逻辑, 但返人类可读字符串 (供 REST /api/push-subscriber-info 用户排查 / Prometheus alert label).

优先级 (与 is_healthy() 一致):

  1. circuit_breaker tripped
  2. consecutive parse errors >= 5
  3. trade requery queue dropped < 60s
  4. resubscribe partial failure < 60s
  5. no push received >= 60s
Source

pub fn snapshot(&self) -> PushHealthSnapshot

F5 snapshot: REST / 诊断层批量读取用.

Source

pub fn render_prometheus(&self) -> String

Render push-health state as Prometheus text exposition.

This mirrors the existing /api/push-subscriber-info snapshot instead of introducing another metrics state source.

Trait Implementations§

Source§

impl Debug for PushHealth

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for PushHealth

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.

§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

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