@workbench-kit/field-remap 0.0.2-prototype.0.2.34 → 0.0.2-prototype.0.2.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workbench-kit/field-remap",
3
- "version": "0.0.2-prototype.0.2.34",
3
+ "version": "0.0.2-prototype.0.2.36",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -14,7 +14,7 @@
14
14
  "!src/**/*.stories.tsx"
15
15
  ],
16
16
  "dependencies": {
17
- "@workbench-kit/contracts": "0.0.2-prototype.0.2.34"
17
+ "@workbench-kit/contracts": "0.0.2-prototype.0.2.36"
18
18
  },
19
19
  "description": "Field remap runtime: convert structure A into structure B via edges and convertToShape.",
20
20
  "publishConfig": {
@@ -56,7 +56,19 @@ export interface FieldRemapPersistenceInput {
56
56
  readonly nextDocument: FieldRemapDocument;
57
57
  readonly expectedRevision: string;
58
58
  readonly nextRevision: string;
59
+ /**
60
+ * Identifies the owner epoch that issued this commit. Persistence adapters must include this
61
+ * identity and the revision pair in their final durable compare-and-swap boundary.
62
+ */
63
+ readonly ownerEpoch: string;
59
64
  readonly signal: AbortSignal;
65
+ /**
66
+ * Returns true only while this exact owner/revision attempt may still commit. A persistence
67
+ * adapter must check this together with `signal.aborted` immediately inside its final atomic
68
+ * commit boundary, after any asynchronous staging work. Once it returns false, this attempt
69
+ * must be unable to mutate durable state.
70
+ */
71
+ isCommitFenceCurrent(): boolean;
60
72
  }
61
73
 
62
74
  export interface FieldRemapTraversalSample {
@@ -622,7 +634,7 @@ export function createFieldRemapProjectionOwner(
622
634
  }
623
635
 
624
636
  async function runPersistence(
625
- input: Omit<FieldRemapPersistenceInput, 'signal'>,
637
+ input: Omit<FieldRemapPersistenceInput, 'ownerEpoch' | 'signal' | 'isCommitFenceCurrent'>,
626
638
  ): Promise<FieldRemapPersistenceResult> {
627
639
  const controller = new AbortController();
628
640
  activePersistenceAbort = controller;
@@ -632,7 +644,21 @@ export function createFieldRemapProjectionOwner(
632
644
  });
633
645
  });
634
646
  const pending: Promise<FieldRemapPersistenceResult> = Promise.resolve()
635
- .then(() => persist({ ...input, signal: controller.signal }))
647
+ .then(() =>
648
+ persist(
649
+ Object.freeze({
650
+ ...input,
651
+ ownerEpoch,
652
+ signal: controller.signal,
653
+ isCommitFenceCurrent: () =>
654
+ !controller.signal.aborted &&
655
+ !closed &&
656
+ !reconciliationPending &&
657
+ activePersistenceAbort === controller &&
658
+ revision() === input.expectedRevision,
659
+ }),
660
+ ),
661
+ )
636
662
  .then((result): FieldRemapPersistenceResult =>
637
663
  isPersistenceResult(result) ? result : { status: 'indeterminate' },
638
664
  )