| 478 | } |
| 479 | |
| 480 | function replayAll( |
| 481 | events: SerializedEvent[], |
| 482 | options?: { readonly publish?: boolean; readonly ownerID?: string; readonly strictOwner?: boolean }, |
| 483 | ) { |
| 484 | return Effect.gen(function* () { |
| 485 | const source = events[0]?.aggregateID |
| 486 | if (!source) return undefined |
| 487 | if (events.some((event) => event.aggregateID !== source)) { |
| 488 | yield* Effect.die( |
| 489 | new InvalidDurableEventError({ |
| 490 | type: events[0]?.type ?? "unknown", |
| 491 | message: "Replay events must belong to the same aggregate", |
| 492 | }), |
| 493 | ) |
| 494 | } |
| 495 | const start = events[0]?.seq ?? 0 |
| 496 | for (const [index, event] of events.entries()) { |
| 497 | const seq = start + index |
| 498 | if (event.seq !== seq) { |
| 499 | yield* Effect.die( |
| 500 | new InvalidDurableEventError({ |
| 501 | type: event.type, |
| 502 | message: `Replay sequence mismatch at index ${index}: expected ${seq}, got ${event.seq}`, |
| 503 | }), |
| 504 | ) |
| 505 | } |
| 506 | } |
| 507 | for (const event of events) { |
| 508 | yield* replay(event, options) |
| 509 | } |
| 510 | return source |
| 511 | }) |
| 512 | } |
| 513 | |
| 514 | function remove(aggregateID: string) { |
| 515 | return db |