feat(lark): add MULTICA_LARK_HUB_DISABLED switch for the channel cutover

The lark_*->channel_* cutover needs a way to make the Feishu bot briefly unavailable WITHOUT taking down the whole multica-api process — the Lark hub is a goroutine inside it, not a separate Deployment. MULTICA_LARK_HUB_DISABLED=true parks the hub at startup: the API serves HTTP normally but never claims a WS lease or opens a Feishu connection.

Rollout (see migration 124 ROLLOUT note): ship the new release with the flag SET so new pods run API-only while old pods (hub on lark_*) drain during the rolling deploy — the two hubs never overlap. After the old pods are gone and migration 124 has run, flip the flag off; the new hub comes up on channel_*. The old backend does NOT need this switch — its hub stops when k8s terminates the old pods, not via a flag. Nil-ing LarkHub reuses the existing not-configured path so both the startup start and the shutdown join skip it.

MUL-3515

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
J
2026-06-23 17:40:07 +08:00
parent 7962a2528a
commit aafe3a31fd

View File

@@ -357,6 +357,19 @@ func main() {
// Lark do not pay any goroutine cost. Lifecycle is bound to
// sweepCtx so the Hub winds down alongside the other long-running
// workers, AFTER the HTTP server has drained.
// Cutover control (MUL-3515): MULTICA_LARK_HUB_DISABLED parks the Lark
// inbound hub WITHOUT taking down the rest of the API — the process still
// serves HTTP normally, it just never claims a WS lease or opens a Feishu
// connection. This is the switch the lark_*->channel_* rollout uses to keep
// the NEW hub dormant while old pods (still running their hub on lark_*)
// drain, so the two never double-process the same bot. Nil-ing LarkHub here
// reuses the same "Lark not configured" path, so the shutdown join below
// also skips it. The operator flips this off after migration 124 + old-pod
// drain to bring the new hub up on channel_*. See migration 124's ROLLOUT note.
if h.LarkHub != nil && os.Getenv("MULTICA_LARK_HUB_DISABLED") == "true" {
slog.Warn("Lark inbound hub disabled via MULTICA_LARK_HUB_DISABLED; API serves normally but no Feishu WebSocket is opened")
h.LarkHub = nil
}
if h.LarkHub != nil {
go h.LarkHub.Run(sweepCtx)
}