Skip to main content

ai_agent/bridge/
poll_config_defaults.rs

1//! Bridge poll interval defaults.
2//!
3//! Translated from openclaudecode/src/bridge/pollConfigDefaults.ts
4
5/// Poll interval when actively seeking work (no transport / below maxSessions).
6/// Governs user-visible "connecting..." latency on initial work pickup and
7/// recovery speed after the server re-dispatches a work item.
8pub const POLL_INTERVAL_MS_NOT_AT_CAPACITY: u64 = 2000;
9
10/// Poll interval when the transport is connected. Runs independently of
11/// heartbeat — when both are enabled, the heartbeat loop breaks out to poll
12/// at this interval. Set to 0 to disable at-capacity polling entirely.
13///
14/// Server-side constraints that bound this value:
15/// - BRIDGE_LAST_POLL_TTL = 4h (Redis key expiry -> environment auto-archived)
16/// - max_poll_stale_seconds = 24h (session-creation health gate, currently disabled)
17///
18/// 10 minutes gives 24× headroom on the Redis TTL while still picking up
19/// server-initiated token-rotation redispatches within one poll cycle.
20/// The transport auto-reconnects internally for 10 minutes on transient WS
21/// failures, so poll is not the recovery path — it's strictly a liveness
22/// signal plus a backstop for permanent close.
23pub const POLL_INTERVAL_MS_AT_CAPACITY: u64 = 600_000;
24
25/// Multisession bridge poll intervals. Defaults match the single-session values
26/// so existing configs without these fields preserve current behavior.
27pub const MULTISESSION_POLL_INTERVAL_MS_NOT_AT_CAPACITY: u64 = POLL_INTERVAL_MS_NOT_AT_CAPACITY;
28pub const MULTISESSION_POLL_INTERVAL_MS_PARTIAL_CAPACITY: u64 = POLL_INTERVAL_MS_NOT_AT_CAPACITY;
29pub const MULTISESSION_POLL_INTERVAL_MS_AT_CAPACITY: u64 = POLL_INTERVAL_MS_AT_CAPACITY;
30
31#[derive(Debug, Clone)]
32pub struct PollIntervalConfig {
33    pub poll_interval_ms_not_at_capacity: u64,
34    pub poll_interval_ms_at_capacity: u64,
35    /// 0 = disabled. When > 0, at-capacity loops send per-work-item heartbeats
36    /// at this interval. Independent of poll_interval_ms_at_capacity — both may
37    /// run (heartbeat periodically yields to poll). 60s gives 5× headroom under
38    /// the server's 300s heartbeat TTL. Named non_exclusive to distinguish from
39    /// the old heartbeat_interval_ms field (either-or semantics in pre-#22145
40    /// clients — heartbeat suppressed poll). Old clients ignore this key; ops
41    /// can set both fields during rollout.
42    pub non_exclusive_heartbeat_interval_ms: u64,
43    pub multisession_poll_interval_ms_not_at_capacity: u64,
44    pub multisession_poll_interval_ms_partial_capacity: u64,
45    pub multisession_poll_interval_ms_at_capacity: u64,
46    /// Poll query param: reclaim unacknowledged work items older than this.
47    /// Matches the server's DEFAULT_RECLAIM_OLDER_THAN_MS (work_service.py:24).
48    /// Enables picking up stale-pending work after JWT expiry, when the prior
49    /// ack failed because the session_ingress_token was already stale.
50    pub reclaim_older_than_ms: u64,
51    /// 0 = disabled. When > 0, push a silent {type:'keep_alive'} frame to
52    /// session-ingress at this interval so upstream proxies don't GC an idle
53    /// remote-control session. 2 min is the default. _v2: bridge-only gate
54    /// (pre-v2 clients read the old key, new clients ignore it).
55    pub session_keepalive_interval_v2_ms: u64,
56}
57
58impl Default for PollIntervalConfig {
59    fn default() -> Self {
60        Self {
61            poll_interval_ms_not_at_capacity: POLL_INTERVAL_MS_NOT_AT_CAPACITY,
62            poll_interval_ms_at_capacity: POLL_INTERVAL_MS_AT_CAPACITY,
63            non_exclusive_heartbeat_interval_ms: 0,
64            multisession_poll_interval_ms_not_at_capacity:
65                MULTISESSION_POLL_INTERVAL_MS_NOT_AT_CAPACITY,
66            multisession_poll_interval_ms_partial_capacity:
67                MULTISESSION_POLL_INTERVAL_MS_PARTIAL_CAPACITY,
68            multisession_poll_interval_ms_at_capacity: MULTISESSION_POLL_INTERVAL_MS_AT_CAPACITY,
69            reclaim_older_than_ms: 5000,
70            session_keepalive_interval_v2_ms: 120_000,
71        }
72    }
73}
74
75/// Default poll interval config.
76pub const DEFAULT_POLL_CONFIG: PollIntervalConfig = PollIntervalConfig {
77    poll_interval_ms_not_at_capacity: POLL_INTERVAL_MS_NOT_AT_CAPACITY,
78    poll_interval_ms_at_capacity: POLL_INTERVAL_MS_AT_CAPACITY,
79    non_exclusive_heartbeat_interval_ms: 0,
80    multisession_poll_interval_ms_not_at_capacity: MULTISESSION_POLL_INTERVAL_MS_NOT_AT_CAPACITY,
81    multisession_poll_interval_ms_partial_capacity: MULTISESSION_POLL_INTERVAL_MS_PARTIAL_CAPACITY,
82    multisession_poll_interval_ms_at_capacity: MULTISESSION_POLL_INTERVAL_MS_AT_CAPACITY,
83    reclaim_older_than_ms: 5000,
84    session_keepalive_interval_v2_ms: 120_000,
85};