@auto-engineer/pipeline 1.67.0 → 1.69.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.
Files changed (70) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +6 -6
  3. package/.turbo/turbo-type-check.log +1 -1
  4. package/CHANGELOG.md +47 -0
  5. package/dist/src/engine/workflow-processor.d.ts +3 -0
  6. package/dist/src/engine/workflow-processor.d.ts.map +1 -1
  7. package/dist/src/engine/workflow-processor.js +50 -7
  8. package/dist/src/engine/workflow-processor.js.map +1 -1
  9. package/dist/src/index.d.ts +0 -2
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/index.js +0 -2
  12. package/dist/src/index.js.map +1 -1
  13. package/dist/src/server/phased-bridge.d.ts +13 -0
  14. package/dist/src/server/phased-bridge.d.ts.map +1 -0
  15. package/dist/src/server/phased-bridge.js +103 -0
  16. package/dist/src/server/phased-bridge.js.map +1 -0
  17. package/dist/src/server/pipeline-server.d.ts +2 -2
  18. package/dist/src/server/pipeline-server.d.ts.map +1 -1
  19. package/dist/src/server/pipeline-server.js +18 -38
  20. package/dist/src/server/pipeline-server.js.map +1 -1
  21. package/dist/src/server/v2-runtime-bridge.d.ts +21 -0
  22. package/dist/src/server/v2-runtime-bridge.d.ts.map +1 -0
  23. package/dist/src/server/v2-runtime-bridge.js +182 -0
  24. package/dist/src/server/v2-runtime-bridge.js.map +1 -0
  25. package/dist/src/store/pipeline-event-store.d.ts.map +1 -1
  26. package/dist/src/store/pipeline-event-store.js +0 -30
  27. package/dist/src/store/pipeline-event-store.js.map +1 -1
  28. package/dist/src/store/pipeline-read-model.d.ts +0 -15
  29. package/dist/src/store/pipeline-read-model.d.ts.map +1 -1
  30. package/dist/src/store/pipeline-read-model.js +0 -49
  31. package/dist/src/store/pipeline-read-model.js.map +1 -1
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/ketchup-plan.md +10 -12
  34. package/package.json +3 -3
  35. package/src/engine/workflow-processor.specs.ts +101 -0
  36. package/src/engine/workflow-processor.ts +54 -8
  37. package/src/index.ts +0 -2
  38. package/src/server/phased-bridge.specs.ts +272 -0
  39. package/src/server/phased-bridge.ts +130 -0
  40. package/src/server/pipeline-server.ts +20 -41
  41. package/src/server/v2-runtime-bridge.specs.ts +347 -0
  42. package/src/server/v2-runtime-bridge.ts +246 -0
  43. package/src/store/pipeline-event-store.specs.ts +0 -137
  44. package/src/store/pipeline-event-store.ts +0 -35
  45. package/src/store/pipeline-read-model.specs.ts +0 -567
  46. package/src/store/pipeline-read-model.ts +0 -71
  47. package/dist/src/projections/phased-execution-projection.d.ts +0 -77
  48. package/dist/src/projections/phased-execution-projection.d.ts.map +0 -1
  49. package/dist/src/projections/phased-execution-projection.js +0 -54
  50. package/dist/src/projections/phased-execution-projection.js.map +0 -1
  51. package/dist/src/projections/settled-instance-projection.d.ts +0 -67
  52. package/dist/src/projections/settled-instance-projection.d.ts.map +0 -1
  53. package/dist/src/projections/settled-instance-projection.js +0 -66
  54. package/dist/src/projections/settled-instance-projection.js.map +0 -1
  55. package/dist/src/runtime/phased-executor.d.ts +0 -34
  56. package/dist/src/runtime/phased-executor.d.ts.map +0 -1
  57. package/dist/src/runtime/phased-executor.js +0 -172
  58. package/dist/src/runtime/phased-executor.js.map +0 -1
  59. package/dist/src/runtime/settled-tracker.d.ts +0 -44
  60. package/dist/src/runtime/settled-tracker.d.ts.map +0 -1
  61. package/dist/src/runtime/settled-tracker.js +0 -170
  62. package/dist/src/runtime/settled-tracker.js.map +0 -1
  63. package/src/projections/phased-execution-projection.specs.ts +0 -202
  64. package/src/projections/phased-execution-projection.ts +0 -146
  65. package/src/projections/settled-instance-projection.specs.ts +0 -296
  66. package/src/projections/settled-instance-projection.ts +0 -160
  67. package/src/runtime/phased-executor.specs.ts +0 -680
  68. package/src/runtime/phased-executor.ts +0 -230
  69. package/src/runtime/settled-tracker.specs.ts +0 -1044
  70. package/src/runtime/settled-tracker.ts +0 -235
@@ -1,230 +0,0 @@
1
- import type { Event } from '@auto-engineer/message-bus';
2
- import type { ForEachPhasedDescriptor } from '../core/descriptors';
3
- import type { PhasedExecutionDocument, PhasedExecutionEvent } from '../projections/phased-execution-projection';
4
- import type { PipelineReadModel } from '../store/pipeline-read-model';
5
-
6
- interface PhasedExecutorOptions {
7
- readModel: PipelineReadModel;
8
- onDispatch: (commandType: string, data: unknown, correlationId: string) => void;
9
- onComplete: (event: Event, correlationId: string) => void;
10
- onEventEmit?: (event: PhasedExecutionEvent) => void | Promise<void>;
11
- }
12
-
13
- export class PhasedExecutor {
14
- private handlerRegistry = new Map<string, ForEachPhasedDescriptor>();
15
- private readonly readModel: PipelineReadModel;
16
- private readonly onDispatch: (commandType: string, data: unknown, correlationId: string) => void;
17
- private readonly onComplete: (event: Event, correlationId: string) => void;
18
- private readonly onEventEmit?: (event: PhasedExecutionEvent) => void | Promise<void>;
19
-
20
- constructor(options: PhasedExecutorOptions) {
21
- this.readModel = options.readModel;
22
- this.onDispatch = options.onDispatch;
23
- this.onComplete = options.onComplete;
24
- this.onEventEmit = options.onEventEmit;
25
- }
26
-
27
- registerHandler(handler: ForEachPhasedDescriptor): void {
28
- const handlerId = this.generateHandlerId(handler);
29
- this.handlerRegistry.set(handlerId, handler);
30
- }
31
-
32
- async startPhased(handler: ForEachPhasedDescriptor, event: Event, correlationId: string): Promise<void> {
33
- const items = handler.itemsSelector(event);
34
- const itemData: Array<{ key: string; phase: string; dispatched: boolean; completed: boolean }> = [];
35
-
36
- for (const item of items) {
37
- const key = handler.completion.itemKey({ type: event.type, data: item as Record<string, unknown> });
38
- const phase = handler.classifier(item);
39
- itemData.push({ key, phase, dispatched: false, completed: false });
40
- }
41
-
42
- const executionId = this.generateSessionId(correlationId, handler);
43
- const handlerId = this.generateHandlerId(handler);
44
-
45
- await this.emitEvent({
46
- type: 'PhasedExecutionStarted',
47
- data: {
48
- executionId,
49
- correlationId,
50
- handlerId,
51
- triggerEvent: event,
52
- items: itemData,
53
- phases: handler.phases,
54
- },
55
- });
56
-
57
- await this.dispatchCurrentPhase(executionId, handler);
58
- }
59
-
60
- async onEventReceived(event: Event, itemKey: string): Promise<void> {
61
- const correlationId = event.correlationId;
62
- if (correlationId === undefined || correlationId === '') return;
63
-
64
- const executions = await this.readModel.getActivePhasedExecutions(correlationId);
65
- const execution = executions.find((ex) => ex.items.some((item) => item.key === itemKey));
66
-
67
- if (execution === undefined) return;
68
-
69
- const itemDoc = execution.items.find((i) => i.key === itemKey);
70
- if (itemDoc === undefined || itemDoc.completed) return;
71
-
72
- const handler = this.handlerRegistry.get(execution.handlerId)!;
73
-
74
- if (handler.stopOnFailure && this.isFailureEvent(event, handler)) {
75
- await this.emitEvent({
76
- type: 'PhasedItemFailed',
77
- data: { executionId: execution.executionId, itemKey, error: event },
78
- });
79
- await this.handleFailure(execution.executionId, handler);
80
- return;
81
- }
82
-
83
- await this.emitEvent({
84
- type: 'PhasedItemCompleted',
85
- data: { executionId: execution.executionId, itemKey, resultEvent: event },
86
- });
87
-
88
- const updatedExecution = (await this.readModel.getPhasedExecution(execution.executionId))!;
89
-
90
- const pendingCount = this.countPendingInPhase(updatedExecution);
91
- if (pendingCount === 0) {
92
- await this.advanceToNextPhase(execution.executionId, handler);
93
- }
94
- }
95
-
96
- async isPhaseComplete(correlationId: string, phase: string): Promise<boolean> {
97
- const executions = await this.readModel.getActivePhasedExecutions(correlationId);
98
- for (const execution of executions) {
99
- const phaseIndex = execution.phases.indexOf(phase);
100
- if (phaseIndex === -1) continue;
101
-
102
- if (execution.currentPhaseIndex > phaseIndex) {
103
- return true;
104
- }
105
-
106
- if (execution.currentPhaseIndex === phaseIndex) {
107
- const pendingCount = this.countPendingInPhase(execution);
108
- return pendingCount === 0;
109
- }
110
-
111
- return false;
112
- }
113
- return false;
114
- }
115
-
116
- private countPendingInPhase(execution: PhasedExecutionDocument): number {
117
- let pending = 0;
118
- const currentPhase = execution.phases[execution.currentPhaseIndex];
119
- for (const item of execution.items) {
120
- if (item.phase === currentPhase && !item.completed) {
121
- pending++;
122
- }
123
- }
124
- return pending;
125
- }
126
-
127
- private async dispatchCurrentPhase(executionId: string, handler: ForEachPhasedDescriptor): Promise<void> {
128
- const execution = (await this.readModel.getPhasedExecution(executionId))!;
129
-
130
- if (execution.currentPhaseIndex >= execution.phases.length) {
131
- await this.completeSession(executionId, handler, true);
132
- return;
133
- }
134
-
135
- const currentPhase = execution.phases[execution.currentPhaseIndex];
136
- const itemsToDispatch = execution.items.filter((i) => i.phase === currentPhase && !i.dispatched);
137
-
138
- if (itemsToDispatch.length === 0) {
139
- await this.advanceToNextPhase(executionId, handler);
140
- return;
141
- }
142
-
143
- for (const item of itemsToDispatch) {
144
- await this.emitEvent({
145
- type: 'PhasedItemDispatched',
146
- data: { executionId, itemKey: item.key, phase: item.phase },
147
- });
148
-
149
- const originalItem = this.findItemByKey(execution.triggerEvent, handler, item.key);
150
- if (originalItem !== undefined) {
151
- const command = handler.emitFactory(originalItem, item.phase, execution.triggerEvent);
152
- this.onDispatch(command.commandType, command.data, execution.correlationId);
153
- }
154
- }
155
- }
156
-
157
- private async advanceToNextPhase(executionId: string, handler: ForEachPhasedDescriptor): Promise<void> {
158
- const execution = (await this.readModel.getPhasedExecution(executionId))!;
159
-
160
- const fromPhase = execution.currentPhaseIndex;
161
- const toPhase = fromPhase + 1;
162
-
163
- await this.emitEvent({
164
- type: 'PhasedPhaseAdvanced',
165
- data: { executionId, fromPhase, toPhase },
166
- });
167
-
168
- await this.dispatchCurrentPhase(executionId, handler);
169
- }
170
-
171
- private async handleFailure(executionId: string, handler: ForEachPhasedDescriptor): Promise<void> {
172
- await this.completeSession(executionId, handler, false);
173
- }
174
-
175
- private async completeSession(
176
- executionId: string,
177
- handler: ForEachPhasedDescriptor,
178
- success: boolean,
179
- ): Promise<void> {
180
- const execution = (await this.readModel.getPhasedExecution(executionId))!;
181
-
182
- const eventDescriptor = success ? handler.completion.successEvent : handler.completion.failureEvent;
183
- const eventType = eventDescriptor.name;
184
-
185
- const results = execution.items.filter((i) => i.completed).map((i) => i.key);
186
- const eventData = success
187
- ? { results, itemCount: execution.items.length }
188
- : { failures: execution.failedItems.map((f) => ({ key: f.key, error: f.error })) };
189
-
190
- const completionEvent: Event = {
191
- type: eventType,
192
- correlationId: execution.correlationId,
193
- data: eventData,
194
- };
195
-
196
- await this.emitEvent({
197
- type: 'PhasedExecutionCompleted',
198
- data: { executionId, success, results },
199
- });
200
-
201
- this.onComplete(completionEvent, execution.correlationId);
202
- }
203
-
204
- private findItemByKey(triggerEvent: Event, handler: ForEachPhasedDescriptor, key: string): unknown {
205
- const items = handler.itemsSelector(triggerEvent);
206
- return items.find((item) => {
207
- const itemKey = handler.completion.itemKey({
208
- type: triggerEvent.type,
209
- data: item as Record<string, unknown>,
210
- });
211
- return itemKey === key;
212
- });
213
- }
214
-
215
- private isFailureEvent(event: Event, handler: ForEachPhasedDescriptor): boolean {
216
- return event.type === handler.completion.failureEvent.name;
217
- }
218
-
219
- private generateSessionId(correlationId: string, handler: ForEachPhasedDescriptor): string {
220
- return `phased-${correlationId}-${handler.eventType}`;
221
- }
222
-
223
- private generateHandlerId(handler: ForEachPhasedDescriptor): string {
224
- return `phased-handler-${handler.eventType}`;
225
- }
226
-
227
- private async emitEvent(event: PhasedExecutionEvent): Promise<void> {
228
- await this.onEventEmit?.(event);
229
- }
230
- }