@cratis/chronicle 6.25.0 → 6.26.0

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.
@@ -8,6 +8,7 @@ export declare class InProcessConstraints {
8
8
  private readonly _definitions;
9
9
  private readonly _constrainedProperties;
10
10
  private readonly _removalTypes;
11
+ private readonly _propertyRemovalTypes;
11
12
  constructor(_definitions: ReadonlyMap<string, ConstraintCapture>);
12
13
  isRemovalOnlyType(eventTypeId: string): boolean;
13
14
  hasRemovalType(eventTypeId: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"InProcessConstraints.d.ts","sourceRoot":"","sources":["../../testing/InProcessConstraints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,IAAI,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAEpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAGpF,MAAM,MAAM,uBAAuB,GAAG,4BAA4B,CAAC;AAiBnE,6FAA6F;AAC7F,qBAAa,oBAAoB;IAIjB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAHzC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAkC;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,YAA6B,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAuDhF;IAED,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE9C;IAED,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAgD;IAE5F,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpE;IAED,yGAAyG;IACzG,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,uBAAuB,EAAE,CAiEzG;IAED,cAAc,CAAC,SAAS,EAAE,mBAAmB,GAAG,mBAAmB,CAElE;IAED,OAAO,CAAC,WAAW;CAGtB"}
1
+ {"version":3,"file":"InProcessConstraints.d.ts","sourceRoot":"","sources":["../../testing/InProcessConstraints.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,IAAI,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAEpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAGpF,MAAM,MAAM,uBAAuB,GAAG,4BAA4B,CAAC;AAiBnE,6FAA6F;AAC7F,qBAAa,oBAAoB;IAKjB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJzC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAkC;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAqB;IAE3D,YAA6B,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAsEhF;IAED,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE9C;IAED,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAgD;IAE5F,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEpE;IAED,yGAAyG;IACzG,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,uBAAuB,EAAE,CA4FzG;IAED,cAAc,CAAC,SAAS,EAAE,mBAAmB,GAAG,mBAAmB,CAElE;IAED,OAAO,CAAC,WAAW;CAGtB"}
@@ -21,6 +21,7 @@ export class InProcessConstraints {
21
21
  _definitions;
22
22
  _constrainedProperties = new Map();
23
23
  _removalTypes = new Set();
24
+ _propertyRemovalTypes = new Set();
24
25
  constructor(_definitions) {
25
26
  this._definitions = _definitions;
26
27
  const coveredTypes = new Map();
@@ -48,6 +49,7 @@ export class InProcessConstraints {
48
49
  }
49
50
  removalOwners.set(id, name);
50
51
  this._removalTypes.add(id);
52
+ this._propertyRemovalTypes.add(id);
51
53
  }
52
54
  for (const entry of unique.eventDefinitions) {
53
55
  const properties = this._constrainedProperties.get(entry.eventTypeId) ?? new Set();
@@ -57,9 +59,23 @@ export class InProcessConstraints {
57
59
  }
58
60
  else if (capture.uniqueEventType) {
59
61
  const unique = capture.uniqueEventType;
60
- if (unique.removedWithEventTypeIds?.length || (unique.eventTypeIds?.length ?? 1) !== 1) {
61
- throw this.unsupported(name, 'Removal and multi-type unique event cycles are not fixture-backed.');
62
+ const ids = unique.eventTypeIds ?? [unique.eventTypeId];
63
+ const removals = unique.removedWithEventTypeIds ?? [];
64
+ const shared = ids.filter(id => removals.includes(id)).length;
65
+ // Exactly the shapes installed by the pinned fixtures: one covered type without removal
66
+ // (constraints.json), two covered types with two separate removers
67
+ // (constraints-event-type-siblings.json), and three covered types with three removers of
68
+ // which one is also covered (constraints-event-type-cycles.json).
69
+ if (!(ids.length === 1 && removals.length === 0) &&
70
+ !(ids.length === 2 && removals.length === 2 && shared === 0) &&
71
+ !(ids.length === 3 && removals.length === 3 && shared === 1)) {
72
+ throw this.unsupported(name, 'This unique event type set and removal combination is not fixture-backed.');
62
73
  }
74
+ // Each cycle fixture installs its definition alone; interaction with other definitions is unproven.
75
+ if (removals.length && _definitions.size !== 1) {
76
+ throw this.unsupported(name, 'Unique event cycles alongside other definitions are not fixture-backed.');
77
+ }
78
+ removals.forEach(id => this._removalTypes.add(id));
63
79
  }
64
80
  else {
65
81
  throw this.unsupported(name, 'Unknown constraint definition.');
@@ -84,7 +100,7 @@ export class InProcessConstraints {
84
100
  }
85
101
  }
86
102
  isRemovalOnlyType(eventTypeId) {
87
- return this._removalTypes.has(eventTypeId) && !this._constrainedProperties.has(eventTypeId);
103
+ return this._propertyRemovalTypes.has(eventTypeId) && !this._constrainedProperties.has(eventTypeId);
88
104
  }
89
105
  hasRemovalType(eventTypeId) { return this._removalTypes.has(eventTypeId); }
90
106
  isConstrainedProperty(eventTypeId, property) {
@@ -121,10 +137,11 @@ export class InProcessConstraints {
121
137
  owners.set(name, claims);
122
138
  }
123
139
  const stagedKeys = new Map();
124
- const stagedTypes = new Set();
140
+ const stagedCycles = new Map();
125
141
  for (const event of incoming) {
126
142
  const type = event.eventType.id.value;
127
143
  const source = event.context.eventSourceId;
144
+ const violationCount = violations.length;
128
145
  for (const [name, definition] of this._definitions) {
129
146
  const property = definition.uniqueConstraint?.eventDefinitions.find(entry => entry.eventTypeId === type)?.properties[0];
130
147
  if (property !== undefined) {
@@ -147,17 +164,45 @@ export class InProcessConstraints {
147
164
  }
148
165
  const uniqueType = definition.uniqueEventType;
149
166
  if (uniqueType && (uniqueType.eventTypeIds ?? [uniqueType.eventTypeId]).includes(type)) {
150
- const first = history.find(prior => prior.context.eventSourceId === source &&
151
- (uniqueType.eventTypeIds ?? [uniqueType.eventTypeId]).includes(prior.eventType.id.value));
152
- const staged = stagedTypes.has(`${name}\u0000${source}`);
153
- if (first || staged) {
154
- violations.push({ EventTypeId: type, SequenceNumber: first?.context.sequenceNumber ?? BigInt(unavailable), ConstraintType: 2,
167
+ const covered = uniqueType.eventTypeIds ?? [uniqueType.eventTypeId];
168
+ const removals = uniqueType.removedWithEventTypeIds ?? [];
169
+ // Durable answer: the earliest covered event after the latest removal for this source.
170
+ let first;
171
+ for (const prior of history) {
172
+ if (prior.context.eventSourceId !== source)
173
+ continue;
174
+ const priorType = prior.eventType.id.value;
175
+ if (removals.includes(priorType))
176
+ first = undefined;
177
+ else if (!first && covered.includes(priorType))
178
+ first = prior;
179
+ }
180
+ const cycles = stagedCycles.get(name) ?? new Map();
181
+ const state = cycles.get(source);
182
+ // A cycle state recorded earlier in this append overrides durable history.
183
+ if (state === 'open' || state === undefined && first) {
184
+ // Durable storage supplies the sequence even when a staged claim causes rejection.
185
+ const sequence = first?.context.sequenceNumber.toString() ?? unavailable;
186
+ violations.push({ EventTypeId: type, SequenceNumber: BigInt(sequence), ConstraintType: 2,
155
187
  ConstraintName: name,
156
- Message: `Event '${type}' violated a unique event type constraint on sequence number ${first?.context.sequenceNumber.toString() ?? unavailable}`,
188
+ Message: `Event '${type}' violated a unique event type constraint on sequence number ${sequence}`,
157
189
  Details: {} });
158
190
  }
159
- else
160
- stagedTypes.add(`${name}\u0000${source}`);
191
+ else {
192
+ cycles.set(source, 'open');
193
+ stagedCycles.set(name, cycles);
194
+ }
195
+ }
196
+ }
197
+ // Kernel batch observers release a cycle only after the entire event validates.
198
+ // A covered-and-removal event first attempts its claim, then releases it.
199
+ if (violations.length === violationCount) {
200
+ for (const [name, definition] of this._definitions) {
201
+ if (definition.uniqueEventType?.removedWithEventTypeIds?.includes(type)) {
202
+ const cycles = stagedCycles.get(name) ?? new Map();
203
+ cycles.set(source, 'released');
204
+ stagedCycles.set(name, cycles);
205
+ }
161
206
  }
162
207
  }
163
208
  }
@@ -1 +1 @@
1
- {"version":3,"file":"InProcessConstraints.js","sourceRoot":"","sources":["../../testing/InProcessConstraints.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"InProcessConstraints.js","sourceRoot":"","sources":["../../testing/InProcessConstraints.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/chronicle",
3
- "version": "6.25.0",
3
+ "version": "6.26.0",
4
4
  "description": "Event sourcing for TypeScript and Node.js — the idiomatic client for Cratis Chronicle, the open-source event-sourcing database",
5
5
  "author": "Cratis",
6
6
  "license": "MIT",
@@ -0,0 +1,236 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import 'reflect-metadata';
5
+ import { readFileSync } from 'node:fs';
6
+ import { chai, describe, it, vi } from 'vitest';
7
+ import { field } from '@cratis/fundamentals';
8
+ import { eventType, getEventTypeMetadata } from '../events/eventTypeDecorator.js';
9
+ import { constraint } from '../events/constraints/constraint.js';
10
+ import { compileConstraints } from '../events/constraints/Constraints.js';
11
+ import type { IConstraint } from '../events/constraints/IConstraint.js';
12
+ import type { IConstraintBuilder } from '../events/constraints/IConstraintBuilder.js';
13
+ import { removeConstraint } from '../events/constraints/removeConstraint.js';
14
+ import { EventScenario, UnsupportedEventSequenceOperation } from './index.js';
15
+ import { InProcessConstraints } from './InProcessConstraints.js';
16
+ import { ReactorScenario } from './ReactorScenario.js';
17
+ import { reactor } from '../reactors/reactor.js';
18
+
19
+ chai.should();
20
+ class OracleCycleFirst { @field(String) label: string; constructor(label: string) { this.label = label; } }
21
+ eventType('OracleCycleFirst')(OracleCycleFirst);
22
+ class OracleCycleSibling { @field(String) label: string; constructor(label: string) { this.label = label; } }
23
+ eventType('OracleCycleSibling')(OracleCycleSibling);
24
+ class OracleCycleRemoved { @field(String) label: string; constructor(label: string) { this.label = label; } }
25
+ eventType('OracleCycleRemoved')(OracleCycleRemoved);
26
+ removeConstraint('OracleCycle')(OracleCycleRemoved);
27
+ class OracleCycleExpired { @field(String) label: string; constructor(label: string) { this.label = label; } }
28
+ eventType('OracleCycleExpired')(OracleCycleExpired);
29
+ removeConstraint('OracleCycle')(OracleCycleExpired);
30
+ class OracleCycleRenewed { @field(String) label: string; constructor(label: string) { this.label = label; } }
31
+ eventType('OracleCycleRenewed')(OracleCycleRenewed);
32
+ removeConstraint('OracleCycle')(OracleCycleRenewed);
33
+ // Same-named uniqueFor declarations merge into one definition covering the whole set.
34
+ class CycleFirst implements IConstraint {
35
+ define(builder: IConstraintBuilder) { builder.uniqueFor(OracleCycleFirst, 'Cycle occupied', 'OracleCycle'); }
36
+ }
37
+ constraint('CycleFirst')(CycleFirst);
38
+ class CycleSibling implements IConstraint {
39
+ define(builder: IConstraintBuilder) { builder.uniqueFor(OracleCycleSibling, undefined, 'OracleCycle'); }
40
+ }
41
+ constraint('CycleSibling')(CycleSibling);
42
+ class CycleRenewed implements IConstraint {
43
+ define(builder: IConstraintBuilder) { builder.uniqueFor(OracleCycleRenewed, undefined, 'OracleCycle'); }
44
+ }
45
+ constraint('CycleRenewed')(CycleRenewed);
46
+
47
+ const aliases = { first: OracleCycleFirst, sibling: OracleCycleSibling, cycleRemoved: OracleCycleRemoved,
48
+ cycleExpired: OracleCycleExpired, renewed: OracleCycleRenewed };
49
+ type Alias = keyof typeof aliases;
50
+ type Input = { source: string; type: Alias; value: string };
51
+ type History = { sequence: string; source: string; sourceType: string; streamType: string; streamId: string;
52
+ type: string; content: Record<string, string>; hash: string };
53
+ type Violation = { EventTypeId: string; SequenceNumber: string; ConstraintType: number; ConstraintName: string;
54
+ Message: string; Details: Record<string, string> };
55
+ type Outcome = { success: boolean; sequences: string[]; violations: Array<{ id: string; message: string; details: Record<string, string> }>;
56
+ wireViolations: Violation[]; errors: string[]; history: History[]; next: string };
57
+ type Fixture = { eventSchemas: Record<string, { eventTypeId: string; properties: Record<string, string> }>;
58
+ constraintDefinitions: Array<{ kind: string; name: string; eventTypes: string[]; removedWithEventTypeIds: string[]; message: string }>;
59
+ isolatedConstraintOperations: Array<{ mode: 'single' | 'batch'; events: Input[] }>;
60
+ expected: { outcomes: Outcome[] } };
61
+ const aliasById = Object.fromEntries(Object.entries(aliases).map(([alias, type]) => [getEventTypeMetadata(type)!.eventType.id.value, alias]));
62
+ const makeEvent = ({ type, value }: Input): object => new aliases[type](value);
63
+ const historyOf = (scenario: EventScenario): History[] => scenario.appendedEvents.map(entry => ({
64
+ sequence: entry.context.sequenceNumber.toString(), source: entry.context.eventSourceId,
65
+ sourceType: entry.context.eventSourceType, streamType: entry.context.eventStreamType, streamId: entry.context.eventStreamId,
66
+ type: entry.eventType.id.value, content: entry.content as Record<string, string>, hash: entry.context.hash
67
+ }));
68
+ const unsupported = async (action: () => unknown, operation: string, reason: string) => {
69
+ await Promise.resolve().then(action).then(() => { throw new Error('Expected rejection'); }, error => {
70
+ (error instanceof UnsupportedEventSequenceOperation).should.be.true;
71
+ (error as Error).message.should.include(`UnsupportedEventSequenceOperation: ${operation}:`);
72
+ (error as Error).message.should.include(reason);
73
+ (error as Error).message.should.include('Use a kernel-backed test.');
74
+ });
75
+ };
76
+ const siblingTypes = [OracleCycleFirst, OracleCycleSibling, OracleCycleRemoved, OracleCycleExpired];
77
+ const cycleTypes = [...siblingTypes, OracleCycleRenewed];
78
+ const shapeReason = 'This unique event type set and removal combination is not fixture-backed.';
79
+
80
+ describe('fixture-backed unique event type cycles', () => {
81
+ for (const [name, selected, constraints] of [
82
+ ['constraints-event-type-siblings', siblingTypes, [CycleFirst, CycleSibling]],
83
+ ['constraints-event-type-cycles', cycleTypes, [CycleFirst, CycleSibling, CycleRenewed]]
84
+ ] as const) {
85
+ it(`matches the pinned kernel ${name}: raw and mapped violations, cycles, hashes and rollback`, async () => {
86
+ const fixture = JSON.parse(readFileSync(new URL(`./fixtures/${name}.json`, import.meta.url), 'utf8')) as Fixture;
87
+ Object.fromEntries(selected.map(type => {
88
+ const metadata = getEventTypeMetadata(type)!;
89
+ return [aliasById[metadata.eventType.id.value], { eventTypeId: metadata.eventType.id.value,
90
+ properties: Object.fromEntries(Object.entries(metadata.schema.properties ?? {}).map(([key, property]) => [key, property.type])) }];
91
+ })).should.deep.equal(fixture.eventSchemas);
92
+ const compiled = compileConstraints({ eventTypes: [...selected], constraints: [...constraints] });
93
+ [...compiled].map(([key, capture]) => ({ kind: 'uniqueEventType', name: key,
94
+ eventTypes: capture.uniqueEventType!.eventTypeIds!.map(id => aliasById[id]),
95
+ removedWithEventTypeIds: capture.uniqueEventType!.removedWithEventTypeIds!.map(id => aliasById[id]),
96
+ message: capture.uniqueEventType!.message ?? ''
97
+ })).should.deep.equal(fixture.constraintDefinitions);
98
+ fixture.isolatedConstraintOperations.length.should.be.greaterThan(0);
99
+ fixture.expected.outcomes.length.should.equal(fixture.isolatedConstraintOperations.length);
100
+ fixture.expected.outcomes.some(outcome => !outcome.success).should.be.true;
101
+ const scenario = new EventScenario({ artifacts: { eventTypes: [...selected], constraints: [...constraints] } });
102
+ const notifications = scenario.eventSequence.appendOperations[Symbol.asyncIterator]();
103
+ const validate = vi.spyOn(InProcessConstraints.prototype, 'validate');
104
+ let count = 0;
105
+ try {
106
+ for (const [index, operation] of fixture.isolatedConstraintOperations.entries()) {
107
+ const expected = fixture.expected.outcomes[index];
108
+ const before = historyOf(scenario);
109
+ const calls = validate.mock.calls.length;
110
+ const nextNotification = notifications.next();
111
+ const results = operation.mode === 'single'
112
+ ? [await scenario.append(operation.events[0].source, makeEvent(operation.events[0]))]
113
+ : await scenario.appendMany(operation.events.map(entry => ({ eventSourceId: entry.source, event: makeEvent(entry) })));
114
+ const notification = (await nextNotification).value!;
115
+ validate.mock.calls.length.should.equal(calls + 1);
116
+ const raw = validate.mock.results.at(-1)?.value as ReturnType<InProcessConstraints['validate']>;
117
+ raw.map(({ SequenceNumber, ...violation }) => ({ ...violation, SequenceNumber: SequenceNumber.toString() }))
118
+ .should.deep.equal(expected.wireViolations);
119
+ notification.length.should.equal(operation.events.length);
120
+ notification.every(item => item.result.isSuccess === expected.success).should.be.true;
121
+ count += operation.events.length;
122
+ scenario.results.length.should.equal(count);
123
+ results.length.should.equal(operation.events.length);
124
+ for (const [position, result] of results.entries()) {
125
+ result.isSuccess.should.equal(expected.success);
126
+ result.sequenceNumber.value.toString().should.equal(expected.success ? expected.sequences[position] : '0');
127
+ result.constraintViolations.map(item => ({ id: item.constraintId, message: item.message, details: item.details }))
128
+ .should.deep.equal(expected.violations);
129
+ result.errors.map(item => item.message).should.deep.equal(expected.errors);
130
+ }
131
+ if (!expected.success) historyOf(scenario).should.deep.equal(before);
132
+ historyOf(scenario).should.deep.equal(expected.history);
133
+ (await scenario.eventSequence.getNextSequenceNumber()).value.toString().should.equal(expected.next);
134
+ }
135
+ } finally {
136
+ validate.mockRestore();
137
+ await notifications.return?.();
138
+ }
139
+ });
140
+ }
141
+
142
+ it('rolls back a release and reclaim in a failing setup call without results or notifications', async () => {
143
+ const scenario = new EventScenario({ artifacts: { eventTypes: siblingTypes, constraints: [CycleFirst, CycleSibling] } });
144
+ const notifications = scenario.eventSequence.appendOperations[Symbol.asyncIterator]();
145
+ try {
146
+ const first = notifications.next();
147
+ await scenario.given.forEventSource('A').events(new OracleCycleFirst('claim'));
148
+ (await first).value!.length.should.equal(1);
149
+ const before = historyOf(scenario);
150
+ await scenario.given.forEventSource('A').events(new OracleCycleRemoved('release'), new OracleCycleFirst('reopen'),
151
+ new OracleCycleSibling('blocked'))
152
+ .then(() => { throw new Error('Invalid setup succeeded'); }, error => {
153
+ (error as Error).message.should.include('EventScenario given setup failed');
154
+ });
155
+ historyOf(scenario).should.deep.equal(before);
156
+ scenario.results.length.should.equal(0);
157
+ (await scenario.eventSequence.getNextSequenceNumber()).value.should.equal(1n);
158
+ const next = notifications.next();
159
+ const blocked = await scenario.append('A', new OracleCycleSibling('still held'));
160
+ blocked.constraintViolations.map(item => item.constraintId).should.deep.equal(['OracleCycle']);
161
+ (await next).value!.map(item => item.event.eventType.id.value).should.deep.equal(['OracleCycleSibling']);
162
+ } finally { await notifications.return?.(); }
163
+ });
164
+
165
+ it('delivers only committed claim and release events to a reactor', async () => {
166
+ const calls: string[] = [];
167
+ @reactor('cycle-reactor')
168
+ class CycleReactor {
169
+ oracleCycleFirst(event: OracleCycleFirst) { calls.push(event.label); }
170
+ oracleCycleSibling(event: OracleCycleSibling) { calls.push(event.label); }
171
+ oracleCycleExpired(event: OracleCycleExpired) { calls.push(event.label); }
172
+ }
173
+ const subject = new ReactorScenario(CycleReactor,
174
+ { artifacts: { eventTypes: siblingTypes, constraints: [CycleFirst, CycleSibling] } });
175
+ await subject.when.forEventSource('A').events(new OracleCycleFirst('claim'));
176
+ await subject.when.forEventSource('A').events(new OracleCycleSibling('blocked'))
177
+ .then(() => { throw new Error('Occupied cycle delivered'); }, error => {
178
+ (error as Error).message.should.include('ReactorScenario action append failed');
179
+ });
180
+ calls.should.deep.equal(['claim']);
181
+ subject.results.length.should.equal(1);
182
+ await subject.when.forEventSource('A').events(new OracleCycleExpired('release'), new OracleCycleSibling('reclaim'));
183
+ calls.should.deep.equal(['claim', 'release', 'reclaim']);
184
+ subject.results.length.should.equal(2);
185
+ });
186
+
187
+ it('rejects unsupported input in a batch and leaves history and results unchanged', async () => {
188
+ const scenario = new EventScenario({ artifacts: { eventTypes: siblingTypes, constraints: [CycleFirst, CycleSibling] } });
189
+ (await scenario.append('A', new OracleCycleFirst('claim'))).isSuccess.should.be.true;
190
+ const before = historyOf(scenario);
191
+ const results = scenario.results;
192
+ await unsupported(() => scenario.appendMany([{ eventSourceId: 'A', event: new OracleCycleExpired('release') },
193
+ { eventSourceId: 'B!', event: new OracleCycleFirst('claim') }]), 'appendMany.source (B!)',
194
+ 'Only simple source identifiers are fixture-backed.');
195
+ historyOf(scenario).should.deep.equal(before);
196
+ scenario.results.should.deep.equal(results);
197
+ const blocked = await scenario.append('A', new OracleCycleSibling('still held'));
198
+ blocked.isSuccess.should.be.false;
199
+ blocked.constraintViolations.map(item => item.message).should.deep.equal(['Cycle occupied']);
200
+ });
201
+
202
+ it('rejects covered and removal type shapes that no fixture installs, at the shape check', async () => {
203
+ await unsupported(() => new EventScenario({ artifacts: {
204
+ eventTypes: [OracleCycleFirst, OracleCycleSibling, OracleCycleRemoved], constraints: [CycleFirst, CycleSibling]
205
+ } }), 'artifacts.constraints (OracleCycle)', shapeReason);
206
+ await unsupported(() => new EventScenario({ artifacts: {
207
+ eventTypes: [OracleCycleFirst, OracleCycleRemoved, OracleCycleRenewed], constraints: [CycleFirst, CycleRenewed]
208
+ } }), 'artifacts.constraints (OracleCycle)', shapeReason);
209
+ await unsupported(() => new EventScenario({ artifacts: {
210
+ eventTypes: [OracleCycleFirst, OracleCycleSibling, OracleCycleRemoved, OracleCycleRenewed],
211
+ constraints: [CycleFirst, CycleSibling, CycleRenewed]
212
+ } }), 'artifacts.constraints (OracleCycle)', shapeReason);
213
+ });
214
+
215
+ it('rejects a fixture-shaped cycle installed alongside another definition', async () => {
216
+ class OtherOnce { @field(String) label = 'other'; }
217
+ eventType('OracleCycleOtherOnce')(OtherOnce);
218
+ class OtherOnceConstraint implements IConstraint {
219
+ define(builder: IConstraintBuilder) { builder.uniqueFor(OtherOnce, undefined, 'OracleCycleOther'); }
220
+ }
221
+ constraint('OracleCycleOther')(OtherOnceConstraint);
222
+ await unsupported(() => new EventScenario({ artifacts: {
223
+ eventTypes: [...siblingTypes, OtherOnce], constraints: [CycleFirst, CycleSibling, OtherOnceConstraint]
224
+ } }), 'artifacts.constraints (OracleCycle)', 'Unique event cycles alongside other definitions are not fixture-backed.');
225
+ });
226
+
227
+ it('rejects a fieldless event-type remover at the schema check', async () => {
228
+ class FieldlessRemoval {}
229
+ eventType('OracleCycleFieldless')(FieldlessRemoval);
230
+ removeConstraint('OracleCycle')(FieldlessRemoval);
231
+ await unsupported(() => new EventScenario({ artifacts: {
232
+ eventTypes: [OracleCycleFirst, OracleCycleSibling, OracleCycleRemoved, FieldlessRemoval],
233
+ constraints: [CycleFirst, CycleSibling]
234
+ } }), 'artifacts.eventTypes.schema (FieldlessRemoval)', 'Only flat, unclassified string/boolean fields are fixture-backed.');
235
+ });
236
+ });
@@ -172,7 +172,7 @@ describe('fixture-backed unscoped constraints', () => {
172
172
  const production = compileConstraints({ eventTypes: [GlobalOnce, SelectedOnce], constraints: [] });
173
173
  production.get('ScenarioSharedOnce')!.uniqueEventType!.eventTypeIds.should.deep.equal(['GlobalOnce', 'SelectedOnce']);
174
174
  unsupported(() => new EventScenario({ artifacts: { eventTypes: [SelectedOnce] } }), 'artifacts.constraints')
175
- .message.should.include('multi-type unique event cycles');
175
+ .message.should.include('This unique event type set and removal combination is not fixture-backed.');
176
176
  });
177
177
 
178
178
  it('rejects removal of a selected unique-event-type constraint at construction', () => {
@@ -183,8 +183,8 @@ describe('fixture-backed unscoped constraints', () => {
183
183
  eventType('OnceNameRemoval')(Removal);
184
184
  removeConstraint('OnceName')(Removal);
185
185
  const message = unsupported(() => new EventScenario({ artifacts: { eventTypes: [Once, Removal] } }), 'artifacts.constraints').message;
186
- message.should.include('Removal');
187
- message.should.include('Use a kernel-backed test.');
186
+ message.should.include('OnceName');
187
+ message.should.include('This unique event type set and removal combination is not fixture-backed.');
188
188
  });
189
189
 
190
190
  it('rejects a global removal decorator targeting a selected constraint', () => {
@@ -374,7 +374,7 @@ describe('fixture-backed unscoped constraints', () => {
374
374
  eventType('AnotherOnce')(AnotherOnce);
375
375
  unique('OracleOnce')(AnotherOnce);
376
376
  unsupported(() => new EventScenario({ artifacts: { eventTypes: [...types, AnotherOnce], constraints: [OracleFluentOnceConstraint] } }), 'artifacts.constraints')
377
- .message.should.include('multi-type unique event cycles');
377
+ .message.should.include('This unique event type set and removal combination is not fixture-backed.');
378
378
  const subject = scenario();
379
379
  await subject.append('A', new OracleKeyClaimed('Alpha'));
380
380
  await subject.append('B', new OracleKeyClaimed('beta'));
@@ -57,7 +57,8 @@ interface Fixture {
57
57
  const directory = new URL('./fixtures/', import.meta.url);
58
58
  const fixtures = readdirSync(directory).filter(name => name.endsWith('.json') &&
59
59
  !['batches.json', 'batch-omitted-routes.json', 'batch-rollback.json', 'builders.json', 'constraints.json', 'constraints-isolation.json', 'constraints-key-domain.json',
60
- 'constraints-property-lifecycle.json', 'constraints-property-covered-removal.json'].includes(name)).map(name => ({
60
+ 'constraints-property-lifecycle.json', 'constraints-property-covered-removal.json', 'constraints-event-type-cycles.json',
61
+ 'constraints-event-type-siblings.json'].includes(name)).map(name => ({
61
62
  name, fixture: JSON.parse(readFileSync(new URL(name, directory), 'utf8')) as Fixture
62
63
  }));
63
64
  const artifacts = { eventTypes: [OracleEventRecorded, AlternateRecorded, BoundaryRecorded], constraints: [] };
@@ -30,6 +30,7 @@ function keyHash(value: string): string {
30
30
  export class InProcessConstraints {
31
31
  private readonly _constrainedProperties = new Map<string, Set<string>>();
32
32
  private readonly _removalTypes = new Set<string>();
33
+ private readonly _propertyRemovalTypes = new Set<string>();
33
34
 
34
35
  constructor(private readonly _definitions: ReadonlyMap<string, ConstraintCapture>) {
35
36
  const coveredTypes = new Map<string, string>();
@@ -56,6 +57,7 @@ export class InProcessConstraints {
56
57
  }
57
58
  removalOwners.set(id, name);
58
59
  this._removalTypes.add(id);
60
+ this._propertyRemovalTypes.add(id);
59
61
  }
60
62
  for (const entry of unique.eventDefinitions) {
61
63
  const properties = this._constrainedProperties.get(entry.eventTypeId) ?? new Set<string>();
@@ -64,9 +66,23 @@ export class InProcessConstraints {
64
66
  }
65
67
  } else if (capture.uniqueEventType) {
66
68
  const unique = capture.uniqueEventType;
67
- if (unique.removedWithEventTypeIds?.length || (unique.eventTypeIds?.length ?? 1) !== 1) {
68
- throw this.unsupported(name, 'Removal and multi-type unique event cycles are not fixture-backed.');
69
+ const ids = unique.eventTypeIds ?? [unique.eventTypeId];
70
+ const removals = unique.removedWithEventTypeIds ?? [];
71
+ const shared = ids.filter(id => removals.includes(id)).length;
72
+ // Exactly the shapes installed by the pinned fixtures: one covered type without removal
73
+ // (constraints.json), two covered types with two separate removers
74
+ // (constraints-event-type-siblings.json), and three covered types with three removers of
75
+ // which one is also covered (constraints-event-type-cycles.json).
76
+ if (!(ids.length === 1 && removals.length === 0) &&
77
+ !(ids.length === 2 && removals.length === 2 && shared === 0) &&
78
+ !(ids.length === 3 && removals.length === 3 && shared === 1)) {
79
+ throw this.unsupported(name, 'This unique event type set and removal combination is not fixture-backed.');
69
80
  }
81
+ // Each cycle fixture installs its definition alone; interaction with other definitions is unproven.
82
+ if (removals.length && _definitions.size !== 1) {
83
+ throw this.unsupported(name, 'Unique event cycles alongside other definitions are not fixture-backed.');
84
+ }
85
+ removals.forEach(id => this._removalTypes.add(id));
70
86
  } else {
71
87
  throw this.unsupported(name, 'Unknown constraint definition.');
72
88
  }
@@ -89,7 +105,7 @@ export class InProcessConstraints {
89
105
  }
90
106
 
91
107
  isRemovalOnlyType(eventTypeId: string): boolean {
92
- return this._removalTypes.has(eventTypeId) && !this._constrainedProperties.has(eventTypeId);
108
+ return this._propertyRemovalTypes.has(eventTypeId) && !this._constrainedProperties.has(eventTypeId);
93
109
  }
94
110
 
95
111
  hasRemovalType(eventTypeId: string): boolean { return this._removalTypes.has(eventTypeId); }
@@ -126,10 +142,11 @@ export class InProcessConstraints {
126
142
  owners.set(name, claims);
127
143
  }
128
144
  const stagedKeys = new Map<string, Map<string, string>>();
129
- const stagedTypes = new Set<string>();
145
+ const stagedCycles = new Map<string, Map<string, 'open' | 'released'>>();
130
146
  for (const event of incoming) {
131
147
  const type = event.eventType.id.value;
132
148
  const source = event.context.eventSourceId;
149
+ const violationCount = violations.length;
133
150
  for (const [name, definition] of this._definitions) {
134
151
  const property = definition.uniqueConstraint?.eventDefinitions.find(entry => entry.eventTypeId === type)?.properties[0];
135
152
  if (property !== undefined) {
@@ -151,15 +168,41 @@ export class InProcessConstraints {
151
168
  }
152
169
  const uniqueType = definition.uniqueEventType;
153
170
  if (uniqueType && (uniqueType.eventTypeIds ?? [uniqueType.eventTypeId]).includes(type)) {
154
- const first = history.find(prior => prior.context.eventSourceId === source &&
155
- (uniqueType.eventTypeIds ?? [uniqueType.eventTypeId]).includes(prior.eventType.id.value));
156
- const staged = stagedTypes.has(`${name}\u0000${source}`);
157
- if (first || staged) {
158
- violations.push({ EventTypeId: type, SequenceNumber: first?.context.sequenceNumber ?? BigInt(unavailable), ConstraintType: 2,
171
+ const covered = uniqueType.eventTypeIds ?? [uniqueType.eventTypeId];
172
+ const removals = uniqueType.removedWithEventTypeIds ?? [];
173
+ // Durable answer: the earliest covered event after the latest removal for this source.
174
+ let first: AppendedEvent | undefined;
175
+ for (const prior of history) {
176
+ if (prior.context.eventSourceId !== source) continue;
177
+ const priorType = prior.eventType.id.value;
178
+ if (removals.includes(priorType)) first = undefined;
179
+ else if (!first && covered.includes(priorType)) first = prior;
180
+ }
181
+ const cycles = stagedCycles.get(name) ?? new Map<string, 'open' | 'released'>();
182
+ const state = cycles.get(source);
183
+ // A cycle state recorded earlier in this append overrides durable history.
184
+ if (state === 'open' || state === undefined && first) {
185
+ // Durable storage supplies the sequence even when a staged claim causes rejection.
186
+ const sequence = first?.context.sequenceNumber.toString() ?? unavailable;
187
+ violations.push({ EventTypeId: type, SequenceNumber: BigInt(sequence), ConstraintType: 2,
159
188
  ConstraintName: name,
160
- Message: `Event '${type}' violated a unique event type constraint on sequence number ${first?.context.sequenceNumber.toString() ?? unavailable}`,
189
+ Message: `Event '${type}' violated a unique event type constraint on sequence number ${sequence}`,
161
190
  Details: {} });
162
- } else stagedTypes.add(`${name}\u0000${source}`);
191
+ } else {
192
+ cycles.set(source, 'open');
193
+ stagedCycles.set(name, cycles);
194
+ }
195
+ }
196
+ }
197
+ // Kernel batch observers release a cycle only after the entire event validates.
198
+ // A covered-and-removal event first attempts its claim, then releases it.
199
+ if (violations.length === violationCount) {
200
+ for (const [name, definition] of this._definitions) {
201
+ if (definition.uniqueEventType?.removedWithEventTypeIds?.includes(type)) {
202
+ const cycles = stagedCycles.get(name) ?? new Map<string, 'open' | 'released'>();
203
+ cycles.set(source, 'released');
204
+ stagedCycles.set(name, cycles);
205
+ }
163
206
  }
164
207
  }
165
208
  }