From a9917e986b7bb46c37cb961e5ab34f9feb0730c1 Mon Sep 17 00:00:00 2001 From: Nan Gao Date: Sat, 24 Oct 2026 16:35:26 +0800 Subject: [PATCH] docs(channels): align leader-lease failover and runtime-config notes with the merged code (#7420) The two-Gateway harness checklist in CONFIGURATION.md said a crashed leader hands its providers over within lease_seconds + grace_seconds; a peer only tries to acquire on its fixed lease_seconds // 3 tick, so the worst case is one renewal interval more (50 s with the defaults), as the leader-lease section of the same file already says. The grace_seconds field description had the same shorter bound. The channels.leader_lease comment in config.example.yaml still said web UI credential changes reach the holder only when it next starts the channel; since #6988 the holder applies them within one renewal interval. The harness `check` footer still listed the IM channel gates as waiting for leader election, which landed in #6843; it now points at the manual channel item in CONFIGURATION.md, which also gains the runtime-config step. --- backend/docs/CONFIGURATION.md | 2 +- .../harness/deerflow/config/channel_leader_lease_config.py | 2 +- config.example.yaml | 5 +++-- scripts/dev_multi_instance.py | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/backend/docs/CONFIGURATION.md b/backend/docs/CONFIGURATION.md index 9cbb42a709..3d8e55b92a 100644 --- a/backend/docs/CONFIGURATION.md +++ b/backend/docs/CONFIGURATION.md @@ -804,7 +804,7 @@ These still need a manual pass: - cancel a run on B from A: it takes effect within about one heartbeat (~10 s; a lower `run_ownership.lease_seconds` makes the boundary easier to observe); - change an MCP filesystem server's args on A: B's local-bash allowlist follows; - edit a skill on A: B's system-prompt skills section changes within 30 s; -- with `DEERFLOW_MI_KEEP_CHANNELS=1` and test bots configured: only one Gateway connects each platform (`GET /api/channels/` reports the same `leader` on both, Telegram logs no `409`, Discord answers once), `stop --kill` hands each provider to the other Gateway within `lease_seconds + grace_seconds`, and a plain `stop ` hands them over on the other Gateway's next tick. +- with `DEERFLOW_MI_KEEP_CHANNELS=1` and test bots configured: only one Gateway connects each platform (`GET /api/channels/` reports the same `leader` on both, Telegram logs no `409`, Discord answers once), `stop --kill` hands each provider to the other Gateway within `lease_seconds + grace_seconds` plus one renewal interval (50 s with the defaults), a plain `stop ` hands them over on the other Gateway's next tick, and credentials saved or a disconnect made with `POST` / `DELETE /api/channels/{provider}/runtime-config` on the non-holder reach the holder within one renewal interval. ### IM channel leader lease (`channels.leader_lease`) diff --git a/backend/packages/harness/deerflow/config/channel_leader_lease_config.py b/backend/packages/harness/deerflow/config/channel_leader_lease_config.py index 56017948e6..63ddfff061 100644 --- a/backend/packages/harness/deerflow/config/channel_leader_lease_config.py +++ b/backend/packages/harness/deerflow/config/channel_leader_lease_config.py @@ -56,7 +56,7 @@ class ChannelLeaderLeaseConfig(BaseModel): grace_seconds: int = Field( default=10, ge=0, - description="Extra time after lease_expires_at before a peer may take an expired lease, absorbing a slow renewal. Worst-case failover is lease_seconds + grace_seconds.", + description="Extra time after lease_expires_at before a peer may take an expired lease, absorbing a slow renewal. Worst-case failover is lease_seconds + grace_seconds plus one renewal interval.", ) @property diff --git a/config.example.yaml b/config.example.yaml index 89774dc823..85e3da2db2 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -3089,8 +3089,9 @@ run_ownership: # # heartbeat; only the holder connects (GitHub webhooks stay on every # # instance). A crashed holder is replaced within lease_seconds + # # grace_seconds plus one renewal interval, a cleanly stopped one on the -# # next heartbeat. Runtime credential changes from the web UI reach the -# # holder only when it next starts the channel. Restart-required. +# # next heartbeat. Credentials saved or a disconnect made from the web UI +# # on any instance reach the holder within one renewal interval. The +# # leader_lease block itself is restart-required. # leader_lease: # # auto (default): on whenever the Gateway sees a multi-process signal # # (GATEWAY_WORKERS / WEB_CONCURRENCY > 1, deployment.multi_instance: true diff --git a/scripts/dev_multi_instance.py b/scripts/dev_multi_instance.py index fab8f991f6..3a7e7ae743 100644 --- a/scripts/dev_multi_instance.py +++ b/scripts/dev_multi_instance.py @@ -697,7 +697,7 @@ MANUAL_CHECKS = ( "cancel a run on B from A: takes effect within about one heartbeat (~10s)", "change an MCP filesystem server's args on A: B's local-bash allowlist follows", "edit a skill on A: B's system-prompt skills section changes within 30s", - "IM channel gates (one leader per platform, failover, runtime-config): once channel leader election lands", + "IM channel gates (one leader per platform, failover, runtime-config): `up` with `DEERFLOW_MI_KEEP_CHANNELS=1` and test bots, then follow the channel item in that section", )