Skip to content

No plugin-reachable transactional write primitive — every migration-class tool rebuilds journal + compensation #4612

Description

@os-zhuang

Found while scoping the D13 promotion tool (cloud#874). Not a blocker for any single tool — the point is that four migration-class consumers are now queued behind the same missing primitive, and each is being forced into the same hand-rolled shape.

Current state

  • The data-engine contract declares an optionalbatch?(requests, { transaction?: boolean }) (packages/spec/src/contracts/data-engine.ts:70-91) — no engine implementation, no callers.
  • driver-turso has real primitives (beginTransaction / commit / rollback, turso-driver.ts:764-776; remote-transport.ts:430-443) — not surfaced through ObjectQL.
  • Plugin-visible multi-row mutation is therefore a JS loop of single-row writes (or multi: true predicate updates). A failure mid-sequence strands partial state; a process crash (as opposed to a thrown error) defeats in-process compensation entirely.

The queued consumers

ToolStatusTables touched
ADR-0105 D13 BU-subtree → org promotion (分立)in design, cloudsys_organization, sys_business_unit(_member), sys_member, sys_user_position, N business objects
ADR-0117 D8 ownership backfillProposedevery object gaining owning_business_unit_id
ADR-0110 org lifecycle hooks(新设/分立/合并)Proposedmemberships, grants, master data
D10 master-data distribution (#4585)blocked on its ADRdistribution/mirror rows per policy

Each independently converges on: dry-run preflight → undo journal → LIFO compensation → re-entrant forward recovery (precedent: cloud organization-lifecycle.ts slug rename). One copy of that machinery is an engineering answer; four copies is a platform debt signal.

Decision needed (one of three)

  1. Surface driver transactions through the engine. The honest cost: middleware/hook semantics inside a transaction (do post-hooks fire before commit?), cache invalidation on rollback, cross-driver support — a real design project, not a plumbing task.
  2. Bless a shared migration-journal primitive — a framework-owned journal + compensation/resume runner that migration tools consume, standardizing the pattern instead of transactionalizing the engine.
  3. Explicitly rule both out and document journal+compensation as the blessed pattern — then at least extract the shared helper so the four consumers stop hand-rolling it.

No urgency ranking implied between 1 and 2; what needs deciding is which debt we are choosing. D13 proceeds on the hand-rolled pattern regardless and simplifies later if 1/2 lands.

Refs: #4346 (the multi: true no-predicate footgun — evidence this write path is sharp), ADR-0110, ADR-0117, cloud#874, cloud#1006.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions