@auto-engineer/pipeline 1.97.0 → 1.97.2
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +5 -5
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +36 -0
- package/dist/src/engine/sqlite-consumer.d.ts.map +1 -1
- package/dist/src/engine/sqlite-consumer.js +5 -3
- package/dist/src/engine/sqlite-consumer.js.map +1 -1
- package/dist/src/engine/sqlite-store.d.ts.map +1 -1
- package/dist/src/engine/sqlite-store.js +2 -0
- package/dist/src/engine/sqlite-store.js.map +1 -1
- package/dist/src/server/pipeline-server.d.ts.map +1 -1
- package/dist/src/server/pipeline-server.js +8 -4
- package/dist/src/server/pipeline-server.js.map +1 -1
- package/dist/src/store/pipeline-event-store.d.ts.map +1 -1
- package/dist/src/store/pipeline-event-store.js +2 -1
- package/dist/src/store/pipeline-event-store.js.map +1 -1
- package/dist/src/store/sqlite-pipeline-event-store.d.ts.map +1 -1
- package/dist/src/store/sqlite-pipeline-event-store.js +2 -0
- package/dist/src/store/sqlite-pipeline-event-store.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/src/engine/sqlite-consumer.ts +5 -3
- package/src/engine/sqlite-store.ts +2 -0
- package/src/server/pipeline-server.specs.ts +8 -7
- package/src/server/pipeline-server.ts +8 -4
- package/src/store/pipeline-event-store.specs.ts +67 -0
- package/src/store/pipeline-event-store.ts +2 -1
- package/src/store/sqlite-pipeline-event-store.ts +2 -0
package/package.json
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
"main": "./dist/src/index.js",
|
|
5
5
|
"types": "./dist/src/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@event-driven-io/
|
|
8
|
-
"@event-driven-io/emmett
|
|
7
|
+
"@event-driven-io/dumbo": "0.13.0-beta.31",
|
|
8
|
+
"@event-driven-io/emmett": "0.43.0-beta.5",
|
|
9
|
+
"@event-driven-io/emmett-sqlite": "0.43.0-beta.5",
|
|
9
10
|
"chokidar": "^3.6.0",
|
|
10
11
|
"cors": "^2.8.5",
|
|
11
12
|
"dotenv": "^16.4.5",
|
|
@@ -13,8 +14,8 @@
|
|
|
13
14
|
"get-port": "^7.1.0",
|
|
14
15
|
"jose": "^5.9.6",
|
|
15
16
|
"nanoid": "^5.0.0",
|
|
16
|
-
"@auto-engineer/
|
|
17
|
-
"@auto-engineer/
|
|
17
|
+
"@auto-engineer/message-bus": "1.97.2",
|
|
18
|
+
"@auto-engineer/file-store": "1.97.2"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
21
|
"@types/cors": "^2.8.17",
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
"publishConfig": {
|
|
24
25
|
"access": "public"
|
|
25
26
|
},
|
|
26
|
-
"version": "1.97.
|
|
27
|
+
"version": "1.97.2",
|
|
27
28
|
"scripts": {
|
|
28
29
|
"build": "tsc && tsx ../../scripts/fix-esm-imports.ts",
|
|
29
30
|
"test": "vitest run --reporter=dot",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dumbo } from '@event-driven-io/dumbo';
|
|
2
|
+
import { sqlite3DumboDriver } from '@event-driven-io/dumbo/sqlite3';
|
|
3
|
+
import { readMessagesBatch } from '@event-driven-io/emmett-sqlite';
|
|
2
4
|
import type { PipelineStore } from './sqlite-store.js';
|
|
3
5
|
|
|
4
6
|
type EventHandler = (event: { type: string; data: Record<string, unknown> }) => void;
|
|
@@ -6,7 +8,7 @@ type EventHandler = (event: { type: string; data: Record<string, unknown> }) =>
|
|
|
6
8
|
export function createConsumer(store: PipelineStore) {
|
|
7
9
|
const handlers = new Map<string, EventHandler>();
|
|
8
10
|
let lastPosition = 0n;
|
|
9
|
-
const
|
|
11
|
+
const pool = dumbo({ driver: sqlite3DumboDriver, fileName: store.fileName });
|
|
10
12
|
|
|
11
13
|
return {
|
|
12
14
|
on(eventType: string, handler: EventHandler): void {
|
|
@@ -14,7 +16,7 @@ export function createConsumer(store: PipelineStore) {
|
|
|
14
16
|
},
|
|
15
17
|
|
|
16
18
|
async poll(): Promise<void> {
|
|
17
|
-
const { messages, currentGlobalPosition } = await readMessagesBatch(
|
|
19
|
+
const { messages, currentGlobalPosition } = await readMessagesBatch(pool.execute, {
|
|
18
20
|
after: lastPosition,
|
|
19
21
|
batchSize: 1000,
|
|
20
22
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getSQLiteEventStore, type SQLiteEventStore } from '@event-driven-io/emmett-sqlite';
|
|
2
|
+
import { sqlite3EventStoreDriver } from '@event-driven-io/emmett-sqlite/sqlite3';
|
|
2
3
|
|
|
3
4
|
export interface PipelineStore {
|
|
4
5
|
eventStore: SQLiteEventStore;
|
|
@@ -9,6 +10,7 @@ export interface PipelineStore {
|
|
|
9
10
|
export async function createPipelineStore(options?: { fileName?: string }): Promise<PipelineStore> {
|
|
10
11
|
const fileName = options?.fileName ?? 'file::memory:?cache=shared';
|
|
11
12
|
const eventStore = getSQLiteEventStore({
|
|
13
|
+
driver: sqlite3EventStoreDriver,
|
|
12
14
|
fileName,
|
|
13
15
|
schema: { autoMigration: 'CreateOrUpdate' },
|
|
14
16
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { dumbo } from '@event-driven-io/dumbo';
|
|
5
|
+
import { sqlite3DumboDriver } from '@event-driven-io/dumbo/sqlite3';
|
|
6
|
+
import { readMessagesBatch } from '@event-driven-io/emmett-sqlite';
|
|
5
7
|
import { nanoid } from 'nanoid';
|
|
6
8
|
import { define } from '../builder/define';
|
|
7
9
|
import { PipelineServer } from './pipeline-server';
|
|
@@ -2376,16 +2378,15 @@ describe('PipelineServer', () => {
|
|
|
2376
2378
|
await new Promise((r) => setTimeout(r, 200));
|
|
2377
2379
|
await server.stop();
|
|
2378
2380
|
|
|
2379
|
-
const
|
|
2380
|
-
const { messages } = await readMessagesBatch(
|
|
2381
|
+
const pool = dumbo({ driver: sqlite3DumboDriver, fileName: tmpFile });
|
|
2382
|
+
const { messages } = await readMessagesBatch(pool.execute, {
|
|
2381
2383
|
after: 0n,
|
|
2382
2384
|
batchSize: 1000,
|
|
2383
2385
|
});
|
|
2384
|
-
|
|
2386
|
+
await pool.close();
|
|
2385
2387
|
|
|
2386
|
-
|
|
2387
|
-
expect(
|
|
2388
|
-
expect(messages.some((m) => m.type === 'PipelineRunStarted')).toBe(true);
|
|
2388
|
+
const types = messages.map((m) => m.type);
|
|
2389
|
+
expect(types).toEqual(expect.arrayContaining(['CommandDispatched', 'PipelineRunStarted']));
|
|
2389
2390
|
|
|
2390
2391
|
fs.unlinkSync(tmpFile);
|
|
2391
2392
|
});
|
|
@@ -6,8 +6,11 @@ import {
|
|
|
6
6
|
type Event,
|
|
7
7
|
type MessageBus,
|
|
8
8
|
} from '@auto-engineer/message-bus';
|
|
9
|
+
import { dumbo } from '@event-driven-io/dumbo';
|
|
10
|
+
import { sqlite3DumboDriver } from '@event-driven-io/dumbo/sqlite3';
|
|
9
11
|
import type { EventStore } from '@event-driven-io/emmett';
|
|
10
|
-
import { getSQLiteEventStore, readMessagesBatch
|
|
12
|
+
import { getSQLiteEventStore, readMessagesBatch } from '@event-driven-io/emmett-sqlite';
|
|
13
|
+
import { sqlite3EventStoreDriver } from '@event-driven-io/emmett-sqlite/sqlite3';
|
|
11
14
|
import cors from 'cors';
|
|
12
15
|
import express from 'express';
|
|
13
16
|
import getPort from 'get-port';
|
|
@@ -180,6 +183,7 @@ export class PipelineServer {
|
|
|
180
183
|
|
|
181
184
|
if (this.storeFileName) {
|
|
182
185
|
this.sqliteEventStore = getSQLiteEventStore({
|
|
186
|
+
driver: sqlite3EventStoreDriver,
|
|
183
187
|
fileName: this.storeFileName,
|
|
184
188
|
schema: { autoMigration: 'CreateOrUpdate' },
|
|
185
189
|
});
|
|
@@ -205,12 +209,12 @@ export class PipelineServer {
|
|
|
205
209
|
}
|
|
206
210
|
|
|
207
211
|
private async replayEventsFromSQLite(): Promise<void> {
|
|
208
|
-
const
|
|
212
|
+
const pool = dumbo({ driver: sqlite3DumboDriver, fileName: this.storeFileName! });
|
|
209
213
|
let lastPosition = 0n;
|
|
210
214
|
|
|
211
215
|
try {
|
|
212
216
|
while (true) {
|
|
213
|
-
const { messages, currentGlobalPosition } = await readMessagesBatch(
|
|
217
|
+
const { messages, currentGlobalPosition } = await readMessagesBatch(pool.execute, {
|
|
214
218
|
after: lastPosition,
|
|
215
219
|
batchSize: 1000,
|
|
216
220
|
});
|
|
@@ -229,7 +233,7 @@ export class PipelineServer {
|
|
|
229
233
|
const isMissingTable = error instanceof Error && error.message.includes('no such table');
|
|
230
234
|
if (!isMissingTable) throw error;
|
|
231
235
|
} finally {
|
|
232
|
-
|
|
236
|
+
await pool.close();
|
|
233
237
|
}
|
|
234
238
|
}
|
|
235
239
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import type { ItemStatusDocument } from '../projections/item-status-projection';
|
|
3
|
+
import type { MessageLogDocument } from '../projections/message-log-projection';
|
|
3
4
|
import type { NodeStatusDocument } from '../projections/node-status-projection';
|
|
4
5
|
import { createPipelineEventStore } from './pipeline-event-store';
|
|
5
6
|
|
|
@@ -169,6 +170,72 @@ describe('PipelineEventStore', () => {
|
|
|
169
170
|
}
|
|
170
171
|
});
|
|
171
172
|
|
|
173
|
+
it('should append a new message log entry for each NodeStatusChanged even on retry', async () => {
|
|
174
|
+
const { eventStore, readModel, close } = createPipelineEventStore();
|
|
175
|
+
try {
|
|
176
|
+
await eventStore.appendToStream('pipeline-c1', [
|
|
177
|
+
{
|
|
178
|
+
type: 'NodeStatusChanged',
|
|
179
|
+
data: {
|
|
180
|
+
correlationId: 'c1',
|
|
181
|
+
commandName: 'RebuildComponentDB',
|
|
182
|
+
nodeId: 'node-1',
|
|
183
|
+
status: 'running',
|
|
184
|
+
previousStatus: 'idle',
|
|
185
|
+
pendingCount: 1,
|
|
186
|
+
endedCount: 0,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'NodeStatusChanged',
|
|
191
|
+
data: {
|
|
192
|
+
correlationId: 'c1',
|
|
193
|
+
commandName: 'RebuildComponentDB',
|
|
194
|
+
nodeId: 'node-1',
|
|
195
|
+
status: 'error',
|
|
196
|
+
previousStatus: 'running',
|
|
197
|
+
pendingCount: 0,
|
|
198
|
+
endedCount: 1,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
await eventStore.appendToStream('pipeline-c1', [
|
|
204
|
+
{
|
|
205
|
+
type: 'NodeStatusChanged',
|
|
206
|
+
data: {
|
|
207
|
+
correlationId: 'c1',
|
|
208
|
+
commandName: 'RebuildComponentDB',
|
|
209
|
+
nodeId: 'node-1',
|
|
210
|
+
status: 'running',
|
|
211
|
+
previousStatus: 'error',
|
|
212
|
+
pendingCount: 1,
|
|
213
|
+
endedCount: 0,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
type: 'NodeStatusChanged',
|
|
218
|
+
data: {
|
|
219
|
+
correlationId: 'c1',
|
|
220
|
+
commandName: 'RebuildComponentDB',
|
|
221
|
+
nodeId: 'node-1',
|
|
222
|
+
status: 'success',
|
|
223
|
+
previousStatus: 'running',
|
|
224
|
+
pendingCount: 0,
|
|
225
|
+
endedCount: 1,
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
]);
|
|
229
|
+
|
|
230
|
+
const messages = await readModel.getMessages('c1');
|
|
231
|
+
const statuses = messages.map((m: MessageLogDocument) => (m.messageData as { status: string }).status);
|
|
232
|
+
|
|
233
|
+
expect(statuses).toEqual(['running', 'error', 'running', 'success']);
|
|
234
|
+
} finally {
|
|
235
|
+
await close();
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
172
239
|
it('should track message stats through CommandDispatched and DomainEventEmitted', async () => {
|
|
173
240
|
const { eventStore, readModel, close } = createPipelineEventStore();
|
|
174
241
|
try {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
inlineProjections,
|
|
8
8
|
inMemorySingleStreamProjection,
|
|
9
9
|
} from '@event-driven-io/emmett';
|
|
10
|
+
import { nanoid } from 'nanoid';
|
|
10
11
|
import type { AwaitEvent, AwaitTrackerDocument } from '../projections/await-tracker-projection';
|
|
11
12
|
import { evolve as evolveAwaitTracker } from '../projections/await-tracker-projection';
|
|
12
13
|
import type { ItemStatusChangedEvent, ItemStatusDocument } from '../projections/item-status-projection';
|
|
@@ -59,7 +60,7 @@ function createProjections() {
|
|
|
59
60
|
return `prs-${event.data.correlationId}`;
|
|
60
61
|
}
|
|
61
62
|
if (event.type === 'NodeStatusChanged') {
|
|
62
|
-
return `nsc-${
|
|
63
|
+
return `nsc-${nanoid()}`;
|
|
63
64
|
}
|
|
64
65
|
if (event.type === 'DomainEventEmitted') {
|
|
65
66
|
return `dee-${event.data.requestId}-${event.data.eventType}`;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getInMemoryDatabase, type InMemoryDatabase } from '@event-driven-io/emmett';
|
|
2
2
|
import { getSQLiteEventStore, type SQLiteEventStore } from '@event-driven-io/emmett-sqlite';
|
|
3
|
+
import { sqlite3EventStoreDriver } from '@event-driven-io/emmett-sqlite/sqlite3';
|
|
3
4
|
import { PipelineReadModel } from './pipeline-read-model';
|
|
4
5
|
|
|
5
6
|
export interface SQLitePipelineEventStoreContext {
|
|
@@ -19,6 +20,7 @@ export async function createSQLitePipelineEventStore(
|
|
|
19
20
|
const database = getInMemoryDatabase();
|
|
20
21
|
|
|
21
22
|
const eventStore = getSQLiteEventStore({
|
|
23
|
+
driver: sqlite3EventStoreDriver,
|
|
22
24
|
fileName: config.fileName,
|
|
23
25
|
schema: { autoMigration: 'CreateOrUpdate' },
|
|
24
26
|
});
|