docs(channel): document non-rolling cutover constraint for the lark->channel migration

Elon deploy review: keeping the lark_* tables (deferred drop) stops old v0.3.27 code from crashing, but is not full expand/contract. Migration 124 is a one-time backfill; afterwards new code runs on channel_* (lease + dedup on channel_*) while pre-cutover code runs on lark_* (lease + dedup on lark_*). If both run concurrently during a rolling deploy, each side claims the same Feishu bot's WS lease on its own table and double-processes inbound events.

This release therefore requires a NON-ROLLING cutover (stop the old hub before applying migration 124 + starting new code; rollback is not lossless once new code writes channel_*). Documented where deployers/reviewers see it: migration 124 header gains a ROLLOUT note; the channel_store.go header is corrected (lark_* tables are retained one release for rollback safety, not "gone"; the store still never touches them). Comment-only — no schema/codegen/behavior change.

MUL-3515

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
J
2026-06-23 17:16:52 +08:00
parent 7af0de4e8c
commit 7962a2528a
2 changed files with 17 additions and 3 deletions

View File

@@ -7,9 +7,11 @@ package lark
// by a channel_* query and translating at the JSONB-config boundary (store.go).
//
// The methods take and return the package's flat domain types (Installation,
// UserBinding, ChatSessionBinding, InboundMessageDedup, BindingToken,
// OutboundCardMessage) and the *Params types in params.go. Only channel_* rows
// are ever read or written; the retired lark_* tables and queries are gone.
// UserBinding, ChatSessionBinding, InboundMessageDedup, BindingTokenRow,
// OutboundCardMessage) and the *Params types in params.go. This store reads
// and writes only channel_*, never lark_*; queries/lark.sql is deleted. The
// physical lark_* tables are retained one release for rollout/rollback safety
// (see migration 124's ROLLOUT note) and dropped by a later cleanup migration.
import (
"context"

View File

@@ -20,6 +20,18 @@
-- ship green on its own. This migration only ADDS channel_* and
-- copies the data forward.
--
-- * ROLLOUT — NON-ROLLING CUTOVER REQUIRED. This backfill is a one-time
-- copy. After it runs, new code reads/writes channel_* while any
-- pre-cutover (v0.3.x) code still reads/writes lark_*: the two table
-- sets never cross-deduplicate, and each side would claim the same
-- Feishu bot's WS lease on its own table and open a duplicate
-- connection, double-processing inbound events (duplicate messages /
-- /issue / runs). So old and new backend hub processes MUST NOT run
-- concurrently against this schema — stop the old hub before applying
-- this migration and starting the new code (recreate, not rolling).
-- Rollback to a pre-cutover build is not lossless once the new code has
-- written Feishu state into channel_*.
--
-- app_secret_encrypted is BYTEA; it is carried into the JSONB config as a
-- base64 string. PostgreSQL's encode(...,'base64') MIME-wraps the output
-- with a newline every 76 chars, and a secretbox-sealed app secret (~72