@auto-engineer/pipeline 1.65.0 → 1.67.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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +6 -6
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +135 -0
- package/dist/src/builder/define-v2.d.ts +101 -0
- package/dist/src/builder/define-v2.d.ts.map +1 -0
- package/dist/src/builder/define-v2.js +209 -0
- package/dist/src/builder/define-v2.js.map +1 -0
- package/dist/src/engine/command-dispatcher.d.ts +31 -0
- package/dist/src/engine/command-dispatcher.d.ts.map +1 -0
- package/dist/src/engine/command-dispatcher.js +26 -0
- package/dist/src/engine/command-dispatcher.js.map +1 -0
- package/dist/src/engine/event-router.d.ts +21 -0
- package/dist/src/engine/event-router.d.ts.map +1 -0
- package/dist/src/engine/event-router.js +22 -0
- package/dist/src/engine/event-router.js.map +1 -0
- package/dist/src/engine/index.d.ts +15 -0
- package/dist/src/engine/index.d.ts.map +1 -0
- package/dist/src/engine/index.js +15 -0
- package/dist/src/engine/index.js.map +1 -0
- package/dist/src/engine/pipeline-engine.d.ts +37 -0
- package/dist/src/engine/pipeline-engine.d.ts.map +1 -0
- package/dist/src/engine/pipeline-engine.js +53 -0
- package/dist/src/engine/pipeline-engine.js.map +1 -0
- package/dist/src/engine/projections/item-status.d.ts +9 -0
- package/dist/src/engine/projections/item-status.d.ts.map +1 -0
- package/dist/src/engine/projections/item-status.js +9 -0
- package/dist/src/engine/projections/item-status.js.map +1 -0
- package/dist/src/engine/projections/latest-run.d.ts +9 -0
- package/dist/src/engine/projections/latest-run.d.ts.map +1 -0
- package/dist/src/engine/projections/latest-run.js +9 -0
- package/dist/src/engine/projections/latest-run.js.map +1 -0
- package/dist/src/engine/projections/message-log.d.ts +9 -0
- package/dist/src/engine/projections/message-log.d.ts.map +1 -0
- package/dist/src/engine/projections/message-log.js +10 -0
- package/dist/src/engine/projections/message-log.js.map +1 -0
- package/dist/src/engine/projections/node-status.d.ts +9 -0
- package/dist/src/engine/projections/node-status.d.ts.map +1 -0
- package/dist/src/engine/projections/node-status.js +9 -0
- package/dist/src/engine/projections/node-status.js.map +1 -0
- package/dist/src/engine/projections/stats.d.ts +9 -0
- package/dist/src/engine/projections/stats.d.ts.map +1 -0
- package/dist/src/engine/projections/stats.js +9 -0
- package/dist/src/engine/projections/stats.js.map +1 -0
- package/dist/src/engine/sqlite-consumer.d.ts +11 -0
- package/dist/src/engine/sqlite-consumer.d.ts.map +1 -0
- package/dist/src/engine/sqlite-consumer.js +27 -0
- package/dist/src/engine/sqlite-consumer.js.map +1 -0
- package/dist/src/engine/sqlite-store.d.ts +10 -0
- package/dist/src/engine/sqlite-store.d.ts.map +1 -0
- package/dist/src/engine/sqlite-store.js +14 -0
- package/dist/src/engine/sqlite-store.js.map +1 -0
- package/dist/src/engine/workflow-processor.d.ts +20 -0
- package/dist/src/engine/workflow-processor.d.ts.map +1 -0
- package/dist/src/engine/workflow-processor.js +36 -0
- package/dist/src/engine/workflow-processor.js.map +1 -0
- package/dist/src/engine/workflows/await-workflow.d.ts +33 -0
- package/dist/src/engine/workflows/await-workflow.d.ts.map +1 -0
- package/dist/src/engine/workflows/await-workflow.js +45 -0
- package/dist/src/engine/workflows/await-workflow.js.map +1 -0
- package/dist/src/engine/workflows/phased-workflow.d.ts +64 -0
- package/dist/src/engine/workflows/phased-workflow.d.ts.map +1 -0
- package/dist/src/engine/workflows/phased-workflow.js +103 -0
- package/dist/src/engine/workflows/phased-workflow.js.map +1 -0
- package/dist/src/engine/workflows/settled-workflow.d.ts +62 -0
- package/dist/src/engine/workflows/settled-workflow.d.ts.map +1 -0
- package/dist/src/engine/workflows/settled-workflow.js +92 -0
- package/dist/src/engine/workflows/settled-workflow.js.map +1 -0
- package/dist/src/graph/types.d.ts +1 -1
- package/dist/src/graph/types.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/server/pipeline-server-v2.d.ts +48 -0
- package/dist/src/server/pipeline-server-v2.d.ts.map +1 -0
- package/dist/src/server/pipeline-server-v2.js +61 -0
- package/dist/src/server/pipeline-server-v2.js.map +1 -0
- package/dist/src/server/pipeline-server.d.ts +5 -1
- package/dist/src/server/pipeline-server.d.ts.map +1 -1
- package/dist/src/server/pipeline-server.js +71 -10
- package/dist/src/server/pipeline-server.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/ketchup-plan.md +13 -0
- package/package.json +3 -3
- package/src/builder/define-v2.specs.ts +236 -0
- package/src/builder/define-v2.ts +351 -0
- package/src/engine/command-dispatcher.specs.ts +62 -0
- package/src/engine/command-dispatcher.ts +46 -0
- package/src/engine/event-router.specs.ts +75 -0
- package/src/engine/event-router.ts +36 -0
- package/src/engine/index.ts +39 -0
- package/src/engine/pipeline-engine-e2e.specs.ts +776 -0
- package/src/engine/pipeline-engine.integration.specs.ts +126 -0
- package/src/engine/pipeline-engine.specs.ts +70 -0
- package/src/engine/pipeline-engine.ts +82 -0
- package/src/engine/projections/item-status.ts +11 -0
- package/src/engine/projections/latest-run.ts +10 -0
- package/src/engine/projections/message-log.ts +11 -0
- package/src/engine/projections/node-status.ts +10 -0
- package/src/engine/projections/projections.specs.ts +176 -0
- package/src/engine/projections/stats.ts +10 -0
- package/src/engine/sqlite-consumer.specs.ts +42 -0
- package/src/engine/sqlite-consumer.ts +34 -0
- package/src/engine/sqlite-store.specs.ts +46 -0
- package/src/engine/sqlite-store.ts +21 -0
- package/src/engine/workflow-processor.specs.ts +37 -0
- package/src/engine/workflow-processor.ts +57 -0
- package/src/engine/workflows/await-workflow.specs.ts +104 -0
- package/src/engine/workflows/await-workflow.ts +66 -0
- package/src/engine/workflows/phased-workflow.specs.ts +383 -0
- package/src/engine/workflows/phased-workflow.ts +153 -0
- package/src/engine/workflows/settled-workflow.specs.ts +364 -0
- package/src/engine/workflows/settled-workflow.ts +139 -0
- package/src/graph/types.ts +1 -1
- package/src/index.ts +2 -0
- package/src/server/pipeline-server-v2.specs.ts +91 -0
- package/src/server/pipeline-server-v2.ts +70 -0
- package/src/server/pipeline-server.specs.ts +327 -134
- package/src/server/pipeline-server.ts +77 -11
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
type Event,
|
|
7
7
|
type MessageBus,
|
|
8
8
|
} from '@auto-engineer/message-bus';
|
|
9
|
+
import type { EventStore } from '@event-driven-io/emmett';
|
|
10
|
+
import { getSQLiteEventStore, readMessagesBatch, sqliteConnection } from '@event-driven-io/emmett-sqlite';
|
|
9
11
|
import cors from 'cors';
|
|
10
12
|
import express from 'express';
|
|
11
13
|
import getPort from 'get-port';
|
|
@@ -36,6 +38,7 @@ export interface CommandHandlerWithMetadata extends CommandHandler {
|
|
|
36
38
|
|
|
37
39
|
export interface PipelineServerConfig {
|
|
38
40
|
port: number;
|
|
41
|
+
storeFileName?: string;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
interface EventWithCorrelation extends Event {
|
|
@@ -58,9 +61,12 @@ export class PipelineServer {
|
|
|
58
61
|
private readonly eventStoreContext: PipelineEventStoreContext;
|
|
59
62
|
private readonly itemKeyExtractors = new Map<string, (data: unknown) => string | undefined>();
|
|
60
63
|
private readonly middleware: express.RequestHandler[] = [];
|
|
61
|
-
private readonly
|
|
64
|
+
private readonly storeFileName?: string;
|
|
65
|
+
private sqliteEventStore?: EventStore;
|
|
66
|
+
private currentSessionId = '';
|
|
62
67
|
|
|
63
68
|
constructor(config: PipelineServerConfig) {
|
|
69
|
+
this.storeFileName = config.storeFileName;
|
|
64
70
|
this.requestedPort = config.port;
|
|
65
71
|
this.actualPort = config.port;
|
|
66
72
|
this.app = express();
|
|
@@ -173,9 +179,61 @@ export class PipelineServer {
|
|
|
173
179
|
});
|
|
174
180
|
});
|
|
175
181
|
|
|
182
|
+
if (this.storeFileName) {
|
|
183
|
+
this.sqliteEventStore = getSQLiteEventStore({
|
|
184
|
+
fileName: this.storeFileName,
|
|
185
|
+
schema: { autoMigration: 'CreateOrUpdate' },
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
await this.replayEventsFromSQLite();
|
|
189
|
+
|
|
190
|
+
const originalAppend = this.eventStoreContext.eventStore.appendToStream.bind(this.eventStoreContext.eventStore);
|
|
191
|
+
this.eventStoreContext.eventStore.appendToStream = async (streamName, events, options) => {
|
|
192
|
+
const result = await originalAppend(streamName, events, options);
|
|
193
|
+
await this.sqliteEventStore!.appendToStream(streamName, events);
|
|
194
|
+
return result;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const restoredSessionId = await this.eventStoreContext.readModel.getLatestCorrelationId();
|
|
199
|
+
if (restoredSessionId) {
|
|
200
|
+
this.currentSessionId = restoredSessionId;
|
|
201
|
+
} else {
|
|
202
|
+
this.currentSessionId = `session-${nanoid()}`;
|
|
203
|
+
await this.broadcastPipelineRunStarted(this.currentSessionId, 'PipelineStarted');
|
|
204
|
+
}
|
|
176
205
|
await this.emitPipelineStartedEvent();
|
|
177
206
|
}
|
|
178
207
|
|
|
208
|
+
private async replayEventsFromSQLite(): Promise<void> {
|
|
209
|
+
const connection = sqliteConnection({ fileName: this.storeFileName! });
|
|
210
|
+
let lastPosition = 0n;
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
while (true) {
|
|
214
|
+
const { messages, currentGlobalPosition } = await readMessagesBatch(connection, {
|
|
215
|
+
after: lastPosition,
|
|
216
|
+
batchSize: 1000,
|
|
217
|
+
});
|
|
218
|
+
if (messages.length === 0) break;
|
|
219
|
+
|
|
220
|
+
for (const message of messages) {
|
|
221
|
+
const metadata: { streamName?: string } = message.metadata ?? {};
|
|
222
|
+
const streamName = metadata.streamName ?? 'pipeline-replay';
|
|
223
|
+
await this.eventStoreContext.eventStore.appendToStream(streamName, [
|
|
224
|
+
{ type: message.type, data: message.data },
|
|
225
|
+
]);
|
|
226
|
+
}
|
|
227
|
+
lastPosition = currentGlobalPosition;
|
|
228
|
+
}
|
|
229
|
+
} catch (error: unknown) {
|
|
230
|
+
const isMissingTable = error instanceof Error && error.message.includes('no such table');
|
|
231
|
+
if (!isMissingTable) throw error;
|
|
232
|
+
} finally {
|
|
233
|
+
connection.close();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
179
237
|
async stop(): Promise<void> {
|
|
180
238
|
this.sseManager.closeAll();
|
|
181
239
|
await new Promise<void>((resolve) => {
|
|
@@ -241,7 +299,7 @@ export class PipelineServer {
|
|
|
241
299
|
const completeGraph = this.markBackLinks(graphWithEnrichedEvents);
|
|
242
300
|
const filterOptions = this.parseFilterOptions(req.query);
|
|
243
301
|
const filteredGraph = filterGraph(completeGraph, filterOptions);
|
|
244
|
-
const correlationId = req.query.correlationId as string | undefined;
|
|
302
|
+
const correlationId = (req.query.correlationId as string | undefined) ?? this.currentSessionId;
|
|
245
303
|
const graphWithStatus = await this.addStatusToCommandNodes(filteredGraph, correlationId);
|
|
246
304
|
|
|
247
305
|
const latestRun = await this.eventStoreContext.readModel.getLatestCorrelationId();
|
|
@@ -270,6 +328,19 @@ export class PipelineServer {
|
|
|
270
328
|
void (async () => {
|
|
271
329
|
const command = req.body as Command;
|
|
272
330
|
|
|
331
|
+
if (command.type === 'RestartPipeline') {
|
|
332
|
+
const previousSessionId = this.currentSessionId;
|
|
333
|
+
this.currentSessionId = `session-${nanoid()}`;
|
|
334
|
+
const requestId = `req-${nanoid()}`;
|
|
335
|
+
await this.broadcastPipelineRunStarted(this.currentSessionId, 'RestartPipeline');
|
|
336
|
+
await this.emitDomainEventEmitted(this.currentSessionId, requestId, 'PipelineRestarted', {
|
|
337
|
+
correlationId: this.currentSessionId,
|
|
338
|
+
previousSessionId,
|
|
339
|
+
});
|
|
340
|
+
res.json({ status: 'ack', sessionId: this.currentSessionId });
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
273
344
|
if (!this.commandHandlers.has(command.type)) {
|
|
274
345
|
res.status(404).json({
|
|
275
346
|
status: 'nack',
|
|
@@ -922,15 +993,10 @@ export class PipelineServer {
|
|
|
922
993
|
const handler = this.commandHandlers.get(command.type);
|
|
923
994
|
if (!handler) return;
|
|
924
995
|
|
|
925
|
-
if (!this.seenCorrelations.has(command.correlationId)) {
|
|
926
|
-
this.seenCorrelations.add(command.correlationId);
|
|
927
|
-
await this.broadcastPipelineRunStarted(command.correlationId, command.type);
|
|
928
|
-
}
|
|
929
|
-
|
|
930
996
|
const itemKey = this.extractItemKey(command.type, command.data, command.requestId);
|
|
931
|
-
await this.getOrCreateItemStatus(
|
|
997
|
+
await this.getOrCreateItemStatus(this.currentSessionId, command.type, itemKey, command.requestId);
|
|
932
998
|
|
|
933
|
-
await this.updateNodeStatus(
|
|
999
|
+
await this.updateNodeStatus(this.currentSessionId, command.type, 'running');
|
|
934
1000
|
await this.settledTracker.onCommandStarted(command);
|
|
935
1001
|
|
|
936
1002
|
const ctx = this.createContext(command.correlationId);
|
|
@@ -956,8 +1022,8 @@ export class PipelineServer {
|
|
|
956
1022
|
}
|
|
957
1023
|
|
|
958
1024
|
const finalStatus = this.getStatusFromEvents(events);
|
|
959
|
-
await this.updateItemStatus(
|
|
960
|
-
await this.updateNodeStatus(
|
|
1025
|
+
await this.updateItemStatus(this.currentSessionId, command.type, itemKey, finalStatus);
|
|
1026
|
+
await this.updateNodeStatus(this.currentSessionId, command.type, finalStatus);
|
|
961
1027
|
|
|
962
1028
|
const eventsWithIds: EventWithCorrelation[] = events.map((event) => ({
|
|
963
1029
|
...event,
|