@acmekit/orchestration 2.13.36 → 2.13.38
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/dist/transaction/datastore/base-in-memory-storage.d.ts +6 -0
- package/dist/transaction/datastore/base-in-memory-storage.d.ts.map +1 -1
- package/dist/transaction/datastore/base-in-memory-storage.js +6 -0
- package/dist/transaction/datastore/base-in-memory-storage.js.map +1 -1
- package/dist/transaction/distributed-transaction.d.ts +22 -0
- package/dist/transaction/distributed-transaction.d.ts.map +1 -1
- package/dist/transaction/distributed-transaction.js +35 -0
- package/dist/transaction/distributed-transaction.js.map +1 -1
- package/dist/transaction/errors.d.ts +0 -14
- package/dist/transaction/errors.d.ts.map +1 -1
- package/dist/transaction/errors.js +1 -37
- package/dist/transaction/errors.js.map +1 -1
- package/dist/transaction/index.d.ts +0 -4
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction/index.js +0 -4
- package/dist/transaction/index.js.map +1 -1
- package/dist/transaction/transaction-orchestrator.d.ts +9 -31
- package/dist/transaction/transaction-orchestrator.d.ts.map +1 -1
- package/dist/transaction/transaction-orchestrator.js +72 -223
- package/dist/transaction/transaction-orchestrator.js.map +1 -1
- package/dist/transaction/types.d.ts +29 -82
- package/dist/transaction/types.d.ts.map +1 -1
- package/dist/transaction/types.js +0 -1
- package/dist/transaction/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +1 -0
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/local-workflow.d.ts +39 -0
- package/dist/workflow/local-workflow.d.ts.map +1 -1
- package/dist/workflow/local-workflow.js +77 -0
- package/dist/workflow/local-workflow.js.map +1 -1
- package/dist/workflow/workflow-manager.d.ts.map +1 -1
- package/dist/workflow/workflow-manager.js +51 -0
- package/dist/workflow/workflow-manager.js.map +1 -1
- package/dist/workflow/workflow-metadata.d.ts +42 -0
- package/dist/workflow/workflow-metadata.d.ts.map +1 -0
- package/dist/workflow/workflow-metadata.js +110 -0
- package/dist/workflow/workflow-metadata.js.map +1 -0
- package/package.json +4 -4
- package/dist/transaction/audit-log.d.ts +0 -66
- package/dist/transaction/audit-log.d.ts.map +0 -1
- package/dist/transaction/audit-log.js +0 -32
- package/dist/transaction/audit-log.js.map +0 -1
- package/dist/transaction/circuit-breaker.d.ts +0 -48
- package/dist/transaction/circuit-breaker.d.ts.map +0 -1
- package/dist/transaction/circuit-breaker.js +0 -59
- package/dist/transaction/circuit-breaker.js.map +0 -1
- package/dist/transaction/metrics.d.ts +0 -71
- package/dist/transaction/metrics.d.ts.map +0 -1
- package/dist/transaction/metrics.js +0 -37
- package/dist/transaction/metrics.js.map +0 -1
- package/dist/transaction/rate-limiter.d.ts +0 -40
- package/dist/transaction/rate-limiter.d.ts.map +0 -1
- package/dist/transaction/rate-limiter.js +0 -31
- package/dist/transaction/rate-limiter.js.map +0 -1
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TransactionOrchestrator = void 0;
|
|
4
4
|
const ulid_1 = require("ulid");
|
|
5
|
-
const circuit_breaker_1 = require("./circuit-breaker");
|
|
6
5
|
const distributed_transaction_1 = require("./distributed-transaction");
|
|
7
6
|
const transaction_step_1 = require("./transaction-step");
|
|
8
7
|
const types_1 = require("./types");
|
|
9
8
|
const utils_1 = require("@acmekit/utils");
|
|
10
9
|
const events_1 = require("events");
|
|
11
10
|
const errors_1 = require("./errors");
|
|
11
|
+
const workflow_manager_1 = require("../workflow/workflow-manager");
|
|
12
12
|
const canMoveForwardStates = new Set([
|
|
13
13
|
utils_1.TransactionStepState.DONE,
|
|
14
14
|
utils_1.TransactionStepState.FAILED,
|
|
@@ -40,56 +40,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
40
40
|
static getWorkflowOptions(modelId) {
|
|
41
41
|
return TransactionOrchestrator.workflowOptions[modelId];
|
|
42
42
|
}
|
|
43
|
-
static appendAuditEntry(transaction, event, step, extra) {
|
|
44
|
-
const store = TransactionOrchestrator.auditLogStore;
|
|
45
|
-
if (!store) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const flow = transaction.getFlow();
|
|
49
|
-
if (!flow.options?.auditLog) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const entry = {
|
|
53
|
-
id: (0, ulid_1.ulid)(),
|
|
54
|
-
timestamp: Date.now(),
|
|
55
|
-
event,
|
|
56
|
-
workflowId: flow.modelId,
|
|
57
|
-
transactionId: flow.transactionId,
|
|
58
|
-
stepId: step?.id,
|
|
59
|
-
stepAction: step?.definition.action,
|
|
60
|
-
handlerType: step
|
|
61
|
-
? step.isCompensating()
|
|
62
|
-
? "compensate"
|
|
63
|
-
: "invoke"
|
|
64
|
-
: undefined,
|
|
65
|
-
attempt: step?.attempts,
|
|
66
|
-
...extra,
|
|
67
|
-
};
|
|
68
|
-
// Fire-and-forget; don't block the transaction
|
|
69
|
-
void Promise.resolve(store.append(entry)).catch(() => { });
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Compute a simple hash of a workflow definition for version tracking.
|
|
73
|
-
* This uses the action names and their order as the version fingerprint.
|
|
74
|
-
*/
|
|
75
|
-
static computeDefinitionHash(definition) {
|
|
76
|
-
const actions = [];
|
|
77
|
-
const queue = [definition];
|
|
78
|
-
while (queue.length > 0) {
|
|
79
|
-
const node = queue.shift();
|
|
80
|
-
if (node.action) {
|
|
81
|
-
actions.push(node.action);
|
|
82
|
-
}
|
|
83
|
-
if (Array.isArray(node.next)) {
|
|
84
|
-
queue.push(...node.next);
|
|
85
|
-
}
|
|
86
|
-
else if (node.next && (0, utils_1.isObject)(node.next)) {
|
|
87
|
-
queue.push(node.next);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// Simple hash: join action names. This is deterministic and fast.
|
|
91
|
-
return actions.join("|");
|
|
92
|
-
}
|
|
93
43
|
constructor({ id, definition, options, isClone, }) {
|
|
94
44
|
super();
|
|
95
45
|
this.invokeSteps = [];
|
|
@@ -218,7 +168,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
218
168
|
flow.state = types_1.TransactionState.COMPENSATING;
|
|
219
169
|
this.flagStepsToRevert(flow);
|
|
220
170
|
this.emit(types_1.DistributedTransactionEvent.COMPENSATE_BEGIN, { transaction });
|
|
221
|
-
TransactionOrchestrator.appendAuditEntry(transaction, types_1.DistributedTransactionEvent.COMPENSATE_BEGIN);
|
|
222
171
|
const result = await this.checkAllSteps(transaction);
|
|
223
172
|
return result;
|
|
224
173
|
}
|
|
@@ -373,6 +322,16 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
373
322
|
}
|
|
374
323
|
static async setStepSuccess(transaction, step, response) {
|
|
375
324
|
const hasStepTimedOut = step.getStates().state === utils_1.TransactionStepState.TIMEOUT;
|
|
325
|
+
// Clear signal index entry when a signal step resolves
|
|
326
|
+
if (step.definition.signal && !step.isCompensating()) {
|
|
327
|
+
const sig = step.definition.signal;
|
|
328
|
+
const flow = transaction.getFlow();
|
|
329
|
+
workflow_manager_1.WorkflowManager.clearSignalIndex(flow.modelId, sig.name, sig.key);
|
|
330
|
+
// Remove from flow's signalRegistry
|
|
331
|
+
if (flow.signalRegistry) {
|
|
332
|
+
delete flow.signalRegistry[sig.name];
|
|
333
|
+
}
|
|
334
|
+
}
|
|
376
335
|
if (step.saveResponse) {
|
|
377
336
|
transaction.addResponse(step.definition.action, step.isCompensating()
|
|
378
337
|
? types_1.TransactionHandlerType.COMPENSATE
|
|
@@ -419,25 +378,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
419
378
|
? types_1.DistributedTransactionEvent.COMPENSATE_STEP_SUCCESS
|
|
420
379
|
: types_1.DistributedTransactionEvent.STEP_SUCCESS;
|
|
421
380
|
transaction.emit(eventName, { step, transaction });
|
|
422
|
-
const durationMs = step.startedAt
|
|
423
|
-
? Date.now() - step.startedAt
|
|
424
|
-
: undefined;
|
|
425
|
-
TransactionOrchestrator.appendAuditEntry(transaction, eventName, step, { durationMs });
|
|
426
|
-
if (TransactionOrchestrator.metricsCollector) {
|
|
427
|
-
const now = Date.now();
|
|
428
|
-
TransactionOrchestrator.metricsCollector.recordStepMetrics({
|
|
429
|
-
workflowId: transaction.getFlow().modelId,
|
|
430
|
-
transactionId: transaction.getFlow().transactionId,
|
|
431
|
-
stepId: step.id,
|
|
432
|
-
action: step.definition.action,
|
|
433
|
-
type: step.isCompensating() ? "compensate" : "invoke",
|
|
434
|
-
status: "success",
|
|
435
|
-
attempt: step.attempts,
|
|
436
|
-
startedAt: step.startedAt ?? now,
|
|
437
|
-
completedAt: now,
|
|
438
|
-
durationMs: durationMs ?? 0,
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
381
|
}
|
|
442
382
|
return {
|
|
443
383
|
stopExecution: !shouldEmit,
|
|
@@ -502,22 +442,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
502
442
|
if (shouldEmit) {
|
|
503
443
|
const eventName = types_1.DistributedTransactionEvent.STEP_SKIPPED;
|
|
504
444
|
transaction.emit(eventName, { step, transaction });
|
|
505
|
-
TransactionOrchestrator.appendAuditEntry(transaction, eventName, step);
|
|
506
|
-
if (TransactionOrchestrator.metricsCollector) {
|
|
507
|
-
const now = Date.now();
|
|
508
|
-
TransactionOrchestrator.metricsCollector.recordStepMetrics({
|
|
509
|
-
workflowId: transaction.getFlow().modelId,
|
|
510
|
-
transactionId: transaction.getFlow().transactionId,
|
|
511
|
-
stepId: step.id,
|
|
512
|
-
action: step.definition.action,
|
|
513
|
-
type: step.isCompensating() ? "compensate" : "invoke",
|
|
514
|
-
status: "skipped",
|
|
515
|
-
attempt: step.attempts,
|
|
516
|
-
startedAt: step.startedAt ?? now,
|
|
517
|
-
completedAt: now,
|
|
518
|
-
durationMs: step.startedAt ? now - step.startedAt : 0,
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
445
|
}
|
|
522
446
|
return {
|
|
523
447
|
stopExecution: !shouldEmit,
|
|
@@ -551,12 +475,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
551
475
|
return result;
|
|
552
476
|
}
|
|
553
477
|
step.failures++;
|
|
554
|
-
// Record circuit breaker failure
|
|
555
|
-
const cbConfig = step.definition.circuitBreaker;
|
|
556
|
-
if (cbConfig && TransactionOrchestrator.circuitBreaker) {
|
|
557
|
-
const cbKey = `${transaction.getFlow().modelId}:${step.definition.action}`;
|
|
558
|
-
void Promise.resolve(TransactionOrchestrator.circuitBreaker.recordFailure(cbKey, cbConfig)).catch(() => { });
|
|
559
|
-
}
|
|
560
478
|
if ((0, utils_1.isErrorLike)(error)) {
|
|
561
479
|
error = (0, utils_1.serializeError)(error);
|
|
562
480
|
}
|
|
@@ -667,31 +585,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
667
585
|
? types_1.DistributedTransactionEvent.COMPENSATE_STEP_FAILURE
|
|
668
586
|
: types_1.DistributedTransactionEvent.STEP_FAILURE;
|
|
669
587
|
transaction.emit(eventName, { step, transaction });
|
|
670
|
-
const durationMs = step.startedAt
|
|
671
|
-
? Date.now() - step.startedAt
|
|
672
|
-
: undefined;
|
|
673
|
-
TransactionOrchestrator.appendAuditEntry(transaction, eventName, step, {
|
|
674
|
-
durationMs,
|
|
675
|
-
errorMessage: (0, utils_1.isErrorLike)(error)
|
|
676
|
-
? error.message
|
|
677
|
-
: String(error?.message ?? "Unknown error"),
|
|
678
|
-
});
|
|
679
|
-
if (TransactionOrchestrator.metricsCollector &&
|
|
680
|
-
step.getStates().status === types_1.TransactionStepStatus.PERMANENT_FAILURE) {
|
|
681
|
-
const now = Date.now();
|
|
682
|
-
TransactionOrchestrator.metricsCollector.recordStepMetrics({
|
|
683
|
-
workflowId: transaction.getFlow().modelId,
|
|
684
|
-
transactionId: transaction.getFlow().transactionId,
|
|
685
|
-
stepId: step.id,
|
|
686
|
-
action: step.definition.action,
|
|
687
|
-
type: step.isCompensating() ? "compensate" : "invoke",
|
|
688
|
-
status: isTimeout ? "timeout" : "failure",
|
|
689
|
-
attempt: step.attempts,
|
|
690
|
-
startedAt: step.startedAt ?? now,
|
|
691
|
-
completedAt: now,
|
|
692
|
-
durationMs: durationMs ?? 0,
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
588
|
}
|
|
696
589
|
return {
|
|
697
590
|
stopExecution: result.stopExecution,
|
|
@@ -755,7 +648,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
755
648
|
step,
|
|
756
649
|
transaction,
|
|
757
650
|
});
|
|
758
|
-
TransactionOrchestrator.appendAuditEntry(transaction, types_1.DistributedTransactionEvent.STEP_BEGIN, step);
|
|
759
651
|
const isAsync = step.isCompensating()
|
|
760
652
|
? step.definition.compensateAsync
|
|
761
653
|
: step.definition.async;
|
|
@@ -799,57 +691,56 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
799
691
|
if (transaction.hasTimeout()) {
|
|
800
692
|
void transaction.clearTransactionTimeout();
|
|
801
693
|
}
|
|
694
|
+
// Clean up signal and query index entries for this transaction
|
|
695
|
+
TransactionOrchestrator.cleanupSignalAndQueryIndex(transaction);
|
|
802
696
|
await transaction.saveCheckpoint().catch((error) => {
|
|
803
697
|
if (!TransactionOrchestrator.isExpectedError(error)) {
|
|
804
698
|
throw error;
|
|
805
699
|
}
|
|
806
700
|
});
|
|
807
701
|
this.emit(types_1.DistributedTransactionEvent.FINISH, { transaction });
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
action: s.definition.action,
|
|
821
|
-
type: s.isCompensating() ? "compensate" : "invoke",
|
|
822
|
-
status: s.getStates().state === utils_1.TransactionStepState.SKIPPED
|
|
823
|
-
? "skipped"
|
|
824
|
-
: s.getStates().state === utils_1.TransactionStepState.TIMEOUT
|
|
825
|
-
? "timeout"
|
|
826
|
-
: s.getStates().state === utils_1.TransactionStepState.FAILED
|
|
827
|
-
? "failure"
|
|
828
|
-
: "success",
|
|
829
|
-
attempt: s.attempts,
|
|
830
|
-
startedAt: s.startedAt,
|
|
831
|
-
completedAt: now,
|
|
832
|
-
durationMs: now - s.startedAt,
|
|
833
|
-
});
|
|
834
|
-
}
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Clean up all signal and query index entries for a transaction.
|
|
705
|
+
*/
|
|
706
|
+
static cleanupSignalAndQueryIndex(transaction) {
|
|
707
|
+
const flow = transaction.getFlow();
|
|
708
|
+
// Clean up signal index entries
|
|
709
|
+
if (flow.signalRegistry) {
|
|
710
|
+
for (const [signalName, _stepAction] of Object.entries(flow.signalRegistry)) {
|
|
711
|
+
const step = TransactionOrchestrator.getStepByAction(flow, _stepAction);
|
|
712
|
+
const key = step?.definition.signal?.key;
|
|
713
|
+
workflow_manager_1.WorkflowManager.clearSignalIndex(flow.modelId, signalName, key);
|
|
835
714
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
715
|
+
}
|
|
716
|
+
// Clean up query index entries
|
|
717
|
+
if (flow.queryHandlers) {
|
|
718
|
+
for (const [queryName, meta] of Object.entries(flow.queryHandlers)) {
|
|
719
|
+
workflow_manager_1.WorkflowManager.clearQueryIndex(flow.modelId, queryName, meta.key);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Parse a duration string like "30s", "5m", "1h", "7d" into seconds.
|
|
725
|
+
*/
|
|
726
|
+
static parseDurationToSeconds(input) {
|
|
727
|
+
const match = input.match(TransactionOrchestrator.DURATION_RE);
|
|
728
|
+
if (!match) {
|
|
729
|
+
throw new Error(`Invalid duration format: "${input}". Expected format: "<number>s", "<number>m", "<number>h", or "<number>d".`);
|
|
730
|
+
}
|
|
731
|
+
const value = parseInt(match[1], 10);
|
|
732
|
+
const unit = match[2];
|
|
733
|
+
switch (unit) {
|
|
734
|
+
case "s":
|
|
735
|
+
return value;
|
|
736
|
+
case "m":
|
|
737
|
+
return value * 60;
|
|
738
|
+
case "h":
|
|
739
|
+
return value * 60 * 60;
|
|
740
|
+
case "d":
|
|
741
|
+
return value * 60 * 60 * 24;
|
|
742
|
+
default:
|
|
743
|
+
throw new Error(`Unknown duration unit: "${unit}"`);
|
|
853
744
|
}
|
|
854
745
|
}
|
|
855
746
|
/**
|
|
@@ -925,29 +816,8 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
925
816
|
: step.definition.compensateAsync),
|
|
926
817
|
idempotency_key: handlerArgs[2].metadata.idempotency_key,
|
|
927
818
|
};
|
|
928
|
-
const cbConfig = step.definition.circuitBreaker;
|
|
929
|
-
const cbKey = cbConfig
|
|
930
|
-
? `${flow.modelId}:${step.definition.action}`
|
|
931
|
-
: undefined;
|
|
932
819
|
const stepHandler = async () => {
|
|
933
|
-
|
|
934
|
-
if (cbConfig && cbKey) {
|
|
935
|
-
const cb = TransactionOrchestrator.circuitBreaker ??
|
|
936
|
-
(TransactionOrchestrator.circuitBreaker =
|
|
937
|
-
new circuit_breaker_1.InMemoryCircuitBreaker());
|
|
938
|
-
const state = typeof cb.maybeTransition === "function"
|
|
939
|
-
? cb.maybeTransition(cbKey, cbConfig)
|
|
940
|
-
: await cb.getState(cbKey);
|
|
941
|
-
if (state === "open") {
|
|
942
|
-
throw new errors_1.CircuitOpenError(step.definition.action);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
const result = await transaction.handler(...handlerArgs);
|
|
946
|
-
// Record circuit breaker success
|
|
947
|
-
if (cbConfig && cbKey && TransactionOrchestrator.circuitBreaker) {
|
|
948
|
-
void Promise.resolve(TransactionOrchestrator.circuitBreaker.recordSuccess(cbKey)).catch(() => { });
|
|
949
|
-
}
|
|
950
|
-
return result;
|
|
820
|
+
return await transaction.handler(...handlerArgs);
|
|
951
821
|
};
|
|
952
822
|
// Return the appropriate promise based on tracing configuration
|
|
953
823
|
if (TransactionOrchestrator.traceStep) {
|
|
@@ -1095,31 +965,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1095
965
|
if (transaction.hasFinished()) {
|
|
1096
966
|
return;
|
|
1097
967
|
}
|
|
1098
|
-
// Version checking and migration (4.5.1 / 4.5.2)
|
|
1099
|
-
const flow = transaction.getFlow();
|
|
1100
|
-
const storedVersion = flow.workflowVersion;
|
|
1101
|
-
const currentVersion = TransactionOrchestrator.computeDefinitionHash(this.definition);
|
|
1102
|
-
if (storedVersion && storedVersion !== currentVersion) {
|
|
1103
|
-
const policy = this.options?.versionPolicy ?? "lenient";
|
|
1104
|
-
// Try to apply migrations first
|
|
1105
|
-
if (this.options?.migrations?.length) {
|
|
1106
|
-
let version = storedVersion;
|
|
1107
|
-
for (const migration of this.options.migrations) {
|
|
1108
|
-
if (migration.fromVersion === version) {
|
|
1109
|
-
migration.migrate(flow);
|
|
1110
|
-
version = migration.toVersion;
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
flow.workflowVersion = version;
|
|
1114
|
-
}
|
|
1115
|
-
// After migrations, check again
|
|
1116
|
-
const afterMigrationVersion = flow.workflowVersion ?? storedVersion;
|
|
1117
|
-
if (afterMigrationVersion !== currentVersion && policy === "strict") {
|
|
1118
|
-
throw new errors_1.WorkflowVersionMismatchError(currentVersion, afterMigrationVersion);
|
|
1119
|
-
}
|
|
1120
|
-
// Update version to current for lenient mode
|
|
1121
|
-
flow.workflowVersion = currentVersion;
|
|
1122
|
-
}
|
|
1123
968
|
const executeNext = async () => {
|
|
1124
969
|
const flow = transaction.getFlow();
|
|
1125
970
|
if (flow.state === types_1.TransactionState.NOT_STARTED) {
|
|
@@ -1132,11 +977,9 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1132
977
|
await transaction.scheduleTransactionTimeout(transaction.getTimeout());
|
|
1133
978
|
}
|
|
1134
979
|
this.emit(types_1.DistributedTransactionEvent.BEGIN, { transaction });
|
|
1135
|
-
TransactionOrchestrator.appendAuditEntry(transaction, types_1.DistributedTransactionEvent.BEGIN);
|
|
1136
980
|
}
|
|
1137
981
|
else {
|
|
1138
982
|
this.emit(types_1.DistributedTransactionEvent.RESUME, { transaction });
|
|
1139
|
-
TransactionOrchestrator.appendAuditEntry(transaction, types_1.DistributedTransactionEvent.RESUME);
|
|
1140
983
|
}
|
|
1141
984
|
return await this.executeNext(transaction);
|
|
1142
985
|
};
|
|
@@ -1169,9 +1012,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1169
1012
|
}
|
|
1170
1013
|
flow.state = types_1.TransactionState.WAITING_TO_COMPENSATE;
|
|
1171
1014
|
flow.cancelledAt = Date.now();
|
|
1172
|
-
if (options?.reason) {
|
|
1173
|
-
flow.cancelReason = options.reason;
|
|
1174
|
-
}
|
|
1175
1015
|
await transaction.saveCheckpoint();
|
|
1176
1016
|
if (options?.preventExecuteNext) {
|
|
1177
1017
|
return;
|
|
@@ -1211,6 +1051,7 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1211
1051
|
transactionId: transactionId,
|
|
1212
1052
|
runId: context?.runId ?? (0, ulid_1.ulid)(),
|
|
1213
1053
|
metadata: flowMetadata,
|
|
1054
|
+
customMetadata: flowMetadata?.customMetadata,
|
|
1214
1055
|
hasAsyncSteps: features.hasAsyncSteps,
|
|
1215
1056
|
hasFailedSteps: false,
|
|
1216
1057
|
hasSkippedOnFailureSteps: false,
|
|
@@ -1222,7 +1063,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1222
1063
|
definition: this.definition,
|
|
1223
1064
|
steps,
|
|
1224
1065
|
_v: 0, // Initialize version to 0
|
|
1225
|
-
workflowVersion: TransactionOrchestrator.computeDefinitionHash(this.definition),
|
|
1226
1066
|
};
|
|
1227
1067
|
return flow;
|
|
1228
1068
|
}
|
|
@@ -1268,6 +1108,21 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1268
1108
|
}
|
|
1269
1109
|
const definitionCopy = { ...obj };
|
|
1270
1110
|
delete definitionCopy.next;
|
|
1111
|
+
// Signal steps are implicitly async
|
|
1112
|
+
if (definitionCopy.signal && !definitionCopy.async) {
|
|
1113
|
+
definitionCopy.async = true;
|
|
1114
|
+
}
|
|
1115
|
+
// Signal steps with timeout: convert duration strings to seconds
|
|
1116
|
+
if (definitionCopy.signal?.timeout && !definitionCopy.timeout) {
|
|
1117
|
+
const t = definitionCopy.signal.timeout;
|
|
1118
|
+
if (typeof t === "string") {
|
|
1119
|
+
definitionCopy.timeout =
|
|
1120
|
+
TransactionOrchestrator.parseDurationToSeconds(t);
|
|
1121
|
+
}
|
|
1122
|
+
else {
|
|
1123
|
+
definitionCopy.timeout = t;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1271
1126
|
const isAsync = !!definitionCopy.async;
|
|
1272
1127
|
const hasRetryInterval = !!(definitionCopy.retryInterval || definitionCopy.retryIntervalAwaiting);
|
|
1273
1128
|
const hasTimeout = !!definitionCopy.timeout;
|
|
@@ -1333,13 +1188,6 @@ class TransactionOrchestrator extends events_1.EventEmitter {
|
|
|
1333
1188
|
* @param flowMetadata - flow metadata which can include event group id for example
|
|
1334
1189
|
*/
|
|
1335
1190
|
async beginTransaction({ transactionId, handler, payload, flowMetadata, context, onLoad, }) {
|
|
1336
|
-
// Check rate limit for new transactions
|
|
1337
|
-
if (this.options?.rateLimit && TransactionOrchestrator.rateLimiter) {
|
|
1338
|
-
const allowed = await TransactionOrchestrator.rateLimiter.acquire(this.id, this.options.rateLimit);
|
|
1339
|
-
if (!allowed) {
|
|
1340
|
-
throw new errors_1.RateLimitExceededError(this.id);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
1191
|
const existingTransaction = await TransactionOrchestrator.loadTransactionById(this.id, transactionId);
|
|
1344
1192
|
let newTransaction = false;
|
|
1345
1193
|
let modelFlow;
|
|
@@ -1513,4 +1361,5 @@ TransactionOrchestrator.DEFAULT_TTL = 30;
|
|
|
1513
1361
|
TransactionOrchestrator.DEFAULT_RETRIES = 0;
|
|
1514
1362
|
TransactionOrchestrator.workflowOptions = {};
|
|
1515
1363
|
TransactionOrchestrator.SEPARATOR = ":";
|
|
1364
|
+
TransactionOrchestrator.DURATION_RE = /^(\d+)(s|m|h|d)$/;
|
|
1516
1365
|
//# sourceMappingURL=transaction-orchestrator.js.map
|