| ... | ... | @@ -1255,6 +1255,77 @@ it.layer(Layer.fresh(makeProjectionPipelinePrefixedTestLayer("t3-projection-atta |
| 1255 | 1255 | ); |
| 1256 | 1256 | |
| 1257 | 1257 | it.layer(BaseTestLayer)("OrchestrationProjectionPipeline", (it) => { |
| 1258 | it.effect("replays a bootstrap backlog larger than the event store default limit", () => |
| 1259 | Effect.gen(function* () { |
| 1260 | const projectionPipeline = yield* OrchestrationProjectionPipeline; |
| 1261 | const eventStore = yield* OrchestrationEventStore; |
| 1262 | const sql = yield* SqlClient.SqlClient; |
| 1263 | const now = "2026-01-01T00:00:00.000Z"; |
| 1264 | const projectId = ProjectId.make("project-bootstrap-backlog"); |
| 1265 | |
| 1266 | const sequenceRows = yield* sql<{ readonly maxSequence: number | null }>` |
| 1267 | SELECT MAX(sequence) AS "maxSequence" FROM orchestration_events |
| 1268 | `; |
| 1269 | const sequenceBeforeBacklog = sequenceRows[0]?.maxSequence ?? 0; |
| 1270 | const appendedEvents = yield* Effect.forEach( |
| 1271 | Array.from({ length: 1_001 }, (_, index) => index), |
| 1272 | (index) => { |
| 1273 | const eventId = EventId.make(`evt-bootstrap-backlog-${index}`); |
| 1274 | const commandId = CommandId.make(`cmd-bootstrap-backlog-${index}`); |
| 1275 | return eventStore.append({ |
| 1276 | type: "project.created", |
| 1277 | eventId, |
| 1278 | aggregateKind: "project", |
| 1279 | aggregateId: projectId, |
| 1280 | occurredAt: now, |
| 1281 | commandId, |
| 1282 | causationEventId: null, |
| 1283 | correlationId: CorrelationId.make(commandId), |
| 1284 | metadata: {}, |
| 1285 | payload: { |
| 1286 | projectId, |
| 1287 | title: `Bootstrap backlog ${index}`, |
| 1288 | workspaceRoot: "/tmp/project-bootstrap-backlog", |
| 1289 | defaultModelSelection: null, |
| 1290 | scripts: [], |
| 1291 | createdAt: now, |
| 1292 | updatedAt: now, |
| 1293 | }, |
| 1294 | }); |
| 1295 | }, |
| 1296 | ); |
| 1297 | const lastSequence = appendedEvents[appendedEvents.length - 1]!.sequence; |
| 1298 | |
| 1299 | yield* Effect.forEach( |
| 1300 | Object.values(ORCHESTRATION_PROJECTOR_NAMES), |
| 1301 | (projector) => { |
| 1302 | const lastAppliedSequence = |
| 1303 | projector === ORCHESTRATION_PROJECTOR_NAMES.projects |
| 1304 | ? sequenceBeforeBacklog |
| 1305 | : lastSequence; |
| 1306 | return sql` |
| 1307 | INSERT INTO projection_state (projector, last_applied_sequence, updated_at) |
| 1308 | VALUES (${projector}, ${lastAppliedSequence}, ${now}) |
| 1309 | ON CONFLICT (projector) |
| 1310 | DO UPDATE SET |
| 1311 | last_applied_sequence = excluded.last_applied_sequence, |
| 1312 | updated_at = excluded.updated_at |
| 1313 | `; |
| 1314 | }, |
| 1315 | { discard: true }, |
| 1316 | ); |
| 1317 | |
| 1318 | yield* projectionPipeline.bootstrap; |
| 1319 | |
| 1320 | const stateRows = yield* sql<{ readonly lastAppliedSequence: number }>` |
| 1321 | SELECT last_applied_sequence AS "lastAppliedSequence" |
| 1322 | FROM projection_state |
| 1323 | WHERE projector = ${ORCHESTRATION_PROJECTOR_NAMES.projects} |
| 1324 | `; |
| 1325 | assert.deepEqual(stateRows, [{ lastAppliedSequence: lastSequence }]); |
| 1326 | }), |
| 1327 | ); |
| 1328 | |
| 1258 | 1329 | it.effect("resumes from projector last_applied_sequence without replaying older events", () => |
| 1259 | 1330 | Effect.gen(function* () { |
| 1260 | 1331 | const projectionPipeline = yield* OrchestrationProjectionPipeline; |