Repository navigation
fix(service-automation): a dispatch to a held connector instance names its fix, not a retry - #28037
Conversation
…s its fix, not a retry A degraded connector instance the platform does not retry (a configuration fault met on a retry, or a credential the upstream refused that only a new value or an edit of the declaration changes) told a connector_action dispatch "the platform retries automatically". The engine's degraded record now carries the hold, and the refusal names what re-attempts it: edit the declaration, or set the stored credential again. An instance on the backoff keeps the retry sentence. The connectors page gains a row for a configuration fault met on a retry. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw8ZC8W9Jeq9E7gY3X
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 3 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 10 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin d5e5e482cf5335a1be4044826217b56e3551f792 && git checkout d5e5e482cf5335a1be4044826217b56e3551f792
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e1dde1a5c15566bcc24d6c641b53d8282fcf655b 824e0f5d9021a0ee063dd1b133235c433fd089e9 && git checkout -B drift-repro e1dde1a5c15566bcc24d6c641b53d8282fcf655b && git merge --no-ff 824e0f5d9021a0ee063dd1b133235c433fd089e9
node scripts/docs-audit/affected-docs.mjs --json e1dde1a5c15566bcc24d6c641b53d8282fcf655b
|
|
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia Seat ACCEPT · PR #28037 · head
|
Requested by Elon · project thread
domain:server#3 · os-elon-musk · session_016WV4cw8ZC8W9Jeq9E7gY3X
Fixes #28016
Clause-②: no
Metadata-protocol: none
Skills-docs: none —
git grep -n -i -e "retries automatically" -e "retried with backoff" -- skillsfinds nothing, andgit grep -n -i degraded -- skillsfinds one line (skills/objectstack-automation/references/integration-recipes.md:9, an unset ref leaves its instance degraded until set), which stays true. The docs row this card owes is in this PR.docs/adr/0097-declarative-connector-instances.md:190still quotes "the platform retries automatically" for every husk; it is governed and outside this card's surface (see Acceptance notes).维护者速读
connector_action派发的拒绝信息不再说「平台会自动重试」,而是写明怎么恢复:编辑声明,或重新设置凭据<ref>(或重启)。真正在退避重试的实例仍说会自动重试。sys_connector_credential+ open-tier resolver chain (env → credential object → vault), reconcile on credential change, install-local prompt for missingcredentialRefs (ruling A on #27230) #27237 之后这类实例根本不会被重试,原来那句话是假的,作者会一直等。degradedHold字段,新增只读方法getConnectorDegradedHold,registerDegradedConnector多一个可选第五参数,原有调用不变。回滚即还原本 PR。builtin/connector-nodes.ts(拒绝文案)、plugin.ts两处挂起点传入 hold、connector-held-dispatch-refusal.test.ts。pnpm --filter @objectstack/service-automation exec vitest run src/connector-held-dispatch-refusal.test.ts src/connector-credential-door.test.ts,预期 30/30 通过。What changes
RegisteredConnectorgains an optionaldegradedHold: ConnectorHold,{ kind: 'declaration' }or{ kind: 'credential', ref }.registerDegradedConnectortakes it as an optional fifth argument (engine delegate and the body inplugin-extension-api.ts), andAutomationEngine.getConnectorDegradedHold(name)reads it. A later degrade of the same name replaces the record, so an instance that goes back on the backoff loses the hold.plugin.tspasses it at the two hold sites.failDegradedConnectorInstance(a configuration fault met on a retry, service-automation: a configuration fault first seen on a degraded connector's backoff retry is logged and skipped, but the instance stays degraded with the stale "could not reach" reason and keeps retrying every 5 minutes #27992) passesdeclaration.holdConnectorForRejectedCredentialpassescredentialwith the row'sreffor a stored value, anddeclarationfor an instance with nocredentialRef(its credential is written into the declaration, so only an edit changes what it sends). An environment or vault value stays on the backoff and passes nothing.builtin/connector-nodes.ts). Held:Dispatch is unavailable until its declaration is edited (or the server restarts); the platform does not retry it.or… until credential '<ref>' is set again (or the server restarts); …. On the backoff: unchanged,… the platform retries automatically.A reason that already ends with a full stop no longer gets a second one (…does not list.. Dispatchbefore).Connector registered DEGRADEDwarn says the materializer does not retry a held instance, and until what. The unheld wording is byte-identical (pinned indegraded-register-cause.test.ts).content/docs/automation/connectors.mdx's failure-modes table gains the row for a configuration fault met on a retry.@objectstack/service-automationpatch.Tests
src/connector-held-dispatch-refusal.test.ts(4): a configuration fault met on the backoff retry; a credential written into the declaration refused by the upstream; control: an unreachable upstream keeps "retries automatically"; the engine record carries the hold, its warn says so, and an unheld degrade clears it.src/connector-credential-door.test.ts(+3, real ObjectQL over SQLite): a stored value refused at materialization (mcp shape) and on a call (rest / openapi shape) says to set credential<ref>again; control: an environment value refused on a call keeps "retries automatically".Serial: open PR #27951 (
engine.ts)#27951 (seat 4) is still open. The two
engine.tsregions do not overlap. This PR's hunks:@@ -667,8 +667,27 @@(RegisteredConnector),@@ -3982,12 +4001,16 @@and@@ -3995,7 +4018,7 @@(theregisterDegradedConnectordelegate),@@ -4142,6 +4165,17 @@(the new reader besidegetConnectorDegradedReason). #27951's hunks againstmain:@@ -6373,6 …,@@ -6398,8 …,@@ -6416,7 …,@@ -6594,38 …(resume paths). Over 2,000 lines apart.Acceptance notes
docs/adr/0097-declarative-connector-instances.md:190says a dispatch to a husk fails with "the platform retries automatically". After this PR that holds only for an instance on the backoff. The ADR is governed and outside this card's surface, so it is left as is.ConnectorDescriptor(GET /api/v1/automation/connectors) does not carry the hold; adding it is apackages/specchange, outside this card. The listing'sdegradedReasonfor a refused credential already says it is not retried.getConnectorDegradedHold, the optionaldegradedHoldfield and fifth argument, theConnectorHoldtype exported fromengine.ts, not from the package entry) are additive and optional; no accept set narrows, henceClause-②: noas ordered.Verification
All readings at head
824e0f5d.Red on main, green with the fix, ablations, restore
main'sengine.ts,plugin-extension-api.ts,plugin.ts,builtin/connector-nodes.tswith the new tests:Tests 4 failed | 25 passed (29). Each held case received… Dispatch is unavailable until that is resolved; the platform retries automatically.(the configuration case as…does not list.. Dispatch …). Both controls passed.connector-held-dispatch-refusal,connector-credential-door,connector-retry-configuration-fault,connector-materialization,degraded-register-cause)Tests 93 passed (93).scripts/ablation-replace.mjs, fix committed first, each restored with blob == HEAD andgit diff HEADempty:builtin/connector-nodes.ts,const hold = engine.getConnectorDegradedHold(cfg.connectorId);toundefined: anchor 1 to 0, blob 2491245ee725 to 98ae59d65b55,Tests 4 failed | 26 passed (30)(the four held dispatch cases; controls green).plugin.ts, the credential-hold argument toundefined: blob 6a0a751a1469 to 11d034a84acc,Tests 3 failed | 27 passed (30)(declared credential, stored credential x2).plugin.ts,failDegradedConnectorInstance's{ kind: 'declaration' }toundefined:Tests 1 failed | 3 passed (4)(the configuration case).Package suite, typecheck, lint
pnpm --filter @objectstack/service-automation exec vitest run:Test Files 224 passed (224),Tests 2848 passed | 1 expected fail (2849).pnpm --filter @objectstack/service-automation run typecheck: exit 0.pnpm lint: exit 0.dispatch-gates families (92 derived, 92 run, 0 NOT-MEASURED)
check-plugin-teardown-shape --self-testafter fetching its pinned commit;check:skill-examplesandcheck:dual-build-cjs-loadsexited 3 on the closure build and 0 after a whole-treeturbo run build(exit 0).dispatch-gates --ran: 92 derived families accounted for, 92 run, 0 NOT-MEASURED.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cw8ZC8W9Jeq9E7gY3X