@auto-engineer/pipeline 1.71.0 → 1.72.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.
@@ -20,6 +20,7 @@ import type { EventDefinition } from '../runtime/event-command-map';
20
20
  import { EventCommandMapper } from '../runtime/event-command-map';
21
21
  import { PipelineRuntime } from '../runtime/pipeline-runtime';
22
22
  import { createPipelineEventStore, type PipelineEventStoreContext } from '../store/pipeline-event-store';
23
+ import { type ConcurrencyConfig, createCommandGate } from './command-gate';
23
24
  import { createPhasedBridge } from './phased-bridge';
24
25
  import { SSEManager } from './sse-manager';
25
26
  import { createV2RuntimeBridge } from './v2-runtime-bridge';
@@ -60,6 +61,7 @@ export class PipelineServer {
60
61
  private readonly sseManager: SSEManager;
61
62
  private readonly eventStoreContext: PipelineEventStoreContext;
62
63
  private readonly itemKeyExtractors = new Map<string, (data: unknown) => string | undefined>();
64
+ private readonly commandGate: ReturnType<typeof createCommandGate>;
63
65
  private readonly middleware: express.RequestHandler[] = [];
64
66
  private readonly storeFileName?: string;
65
67
  private sqliteEventStore?: EventStore;
@@ -90,6 +92,7 @@ export class PipelineServer {
90
92
  },
91
93
  });
92
94
  this.sseManager = new SSEManager();
95
+ this.commandGate = createCommandGate();
93
96
  }
94
97
 
95
98
  get port(): number {
@@ -120,6 +123,10 @@ export class PipelineServer {
120
123
  this.itemKeyExtractors.set(commandType, extractor);
121
124
  }
122
125
 
126
+ registerConcurrency(commandType: string, config: ConcurrencyConfig): void {
127
+ this.commandGate.register(commandType, config);
128
+ }
129
+
123
130
  registerPipeline(pipeline: Pipeline): void {
124
131
  this.pipelines.set(pipeline.descriptor.name, pipeline);
125
132
  this.runtimes.set(pipeline.descriptor.name, new PipelineRuntime(pipeline.descriptor));
@@ -973,13 +980,23 @@ export class PipelineServer {
973
980
  const handler = this.commandHandlers.get(command.type);
974
981
  if (!handler) return;
975
982
 
983
+ await this.commandGate.run(command.type, command.data, async (signal) => {
984
+ await this.executeCommand(command, handler, signal);
985
+ });
986
+ }
987
+
988
+ private async executeCommand(
989
+ command: Command & { correlationId: string; requestId: string },
990
+ handler: CommandHandlerWithMetadata,
991
+ signal: AbortSignal,
992
+ ): Promise<void> {
976
993
  const itemKey = this.extractItemKey(command.type, command.data, command.requestId);
977
994
  await this.getOrCreateItemStatus(this.currentSessionId, command.type, itemKey, command.requestId);
978
995
 
979
996
  await this.updateNodeStatus(this.currentSessionId, command.type, 'running');
980
997
  this.settledBridge.onCommandStarted(command, this.currentSessionId);
981
998
 
982
- const ctx = this.createContext(command.correlationId);
999
+ const ctx = this.createContext(command.correlationId, signal);
983
1000
  let events: Event[];
984
1001
  try {
985
1002
  const resultEvent = await handler.handle(command, ctx);
@@ -1001,6 +1018,8 @@ export class PipelineServer {
1001
1018
  ];
1002
1019
  }
1003
1020
 
1021
+ if (signal.aborted) return;
1022
+
1004
1023
  const finalStatus = this.getStatusFromEvents(events);
1005
1024
  await this.updateItemStatus(this.currentSessionId, command.type, itemKey, finalStatus);
1006
1025
  await this.updateNodeStatus(this.currentSessionId, command.type, finalStatus);
@@ -1073,9 +1092,10 @@ export class PipelineServer {
1073
1092
  await Promise.all(runtimes.map((runtime) => runtime.handleEvent(event, ctx)));
1074
1093
  }
1075
1094
 
1076
- private createContext(correlationId: string): PipelineContext {
1095
+ private createContext(correlationId: string, signal?: AbortSignal): PipelineContext {
1077
1096
  return {
1078
1097
  correlationId,
1098
+ signal,
1079
1099
  emit: async (type: string, data: unknown) => {
1080
1100
  const requestId = `req-${nanoid()}`;
1081
1101
  const event: EventWithCorrelation = {