@voltro/workflow 0.86.0 → 0.87.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/CHANGELOG.md +5321 -0
- package/THIRD-PARTY-NOTICES.md +1130 -11
- package/dist/cluster.d.ts +111 -27
- package/dist/cluster.js +12 -8
- package/dist/clusterCron.js +17 -9
- package/dist/clusterLayer.js +104 -69
- package/dist/clusterRunnerLayer.js +26 -16
- package/dist/clusterShardGroups.js +33 -0
- package/dist/clusterTestSuite.d.ts +23 -0
- package/dist/clusterTestSuite.js +142 -112
- package/dist/index.d.ts +47 -22
- package/dist/index.js +24 -23
- package/dist/journalRoutingGuard.js +50 -0
- package/dist/journalRoutingLayout.js +47 -0
- package/dist/journalRoutingLock.js +39 -0
- package/dist/journalRoutingMaintenance.js +24 -0
- package/dist/journalRoutingMessageStorage.js +32 -0
- package/dist/journalRoutingNamespace.js +23 -0
- package/dist/journalRoutingRuntime.js +33 -0
- package/dist/journalRoutingSharding.js +28 -0
- package/dist/journalRoutingState.js +93 -0
- package/dist/journalRoutingTable.js +11 -0
- package/dist/journalRoutingTransaction.js +16 -0
- package/dist/workflowExecutorRouting.js +33 -0
- package/dist/workflowRestartDispatch.js +29 -23
- package/dist/workflowRestartReservation.js +156 -155
- package/dist/workflowResumeDispatch.js +17 -16
- package/dist/workflowRuntimeReadiness.js +12 -0
- package/dist/workflowShardRelocation.js +58 -0
- package/dist/workflowShardRelocationSql.js +72 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -603,9 +603,10 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
603
603
|
kind: "settled";
|
|
604
604
|
request: {
|
|
605
605
|
readonly id: string;
|
|
606
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
606
607
|
readonly result: {
|
|
607
608
|
readonly kind: "confirmed" | "already-terminal";
|
|
608
|
-
readonly status: "failed" | "
|
|
609
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
609
610
|
readonly completedAt: number;
|
|
610
611
|
readonly output: unknown;
|
|
611
612
|
readonly errorTag: string | null;
|
|
@@ -616,7 +617,6 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
616
617
|
readonly enteredAt: number;
|
|
617
618
|
readonly generation: string;
|
|
618
619
|
} | null;
|
|
619
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
620
620
|
readonly generation: string;
|
|
621
621
|
readonly runId: string;
|
|
622
622
|
readonly requestedAt: number;
|
|
@@ -643,9 +643,10 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
643
643
|
kind: "unknown";
|
|
644
644
|
request: {
|
|
645
645
|
readonly id: string;
|
|
646
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
646
647
|
readonly result: {
|
|
647
648
|
readonly kind: "confirmed" | "already-terminal";
|
|
648
|
-
readonly status: "failed" | "
|
|
649
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
649
650
|
readonly completedAt: number;
|
|
650
651
|
readonly output: unknown;
|
|
651
652
|
readonly errorTag: string | null;
|
|
@@ -656,7 +657,6 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
656
657
|
readonly enteredAt: number;
|
|
657
658
|
readonly generation: string;
|
|
658
659
|
} | null;
|
|
659
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
660
660
|
readonly generation: string;
|
|
661
661
|
readonly runId: string;
|
|
662
662
|
readonly requestedAt: number;
|
|
@@ -683,9 +683,10 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
683
683
|
kind: "superseded";
|
|
684
684
|
request: {
|
|
685
685
|
readonly id: string;
|
|
686
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
686
687
|
readonly result: {
|
|
687
688
|
readonly kind: "confirmed" | "already-terminal";
|
|
688
|
-
readonly status: "failed" | "
|
|
689
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
689
690
|
readonly completedAt: number;
|
|
690
691
|
readonly output: unknown;
|
|
691
692
|
readonly errorTag: string | null;
|
|
@@ -696,7 +697,6 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
696
697
|
readonly enteredAt: number;
|
|
697
698
|
readonly generation: string;
|
|
698
699
|
} | null;
|
|
699
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
700
700
|
readonly generation: string;
|
|
701
701
|
readonly runId: string;
|
|
702
702
|
readonly requestedAt: number;
|
|
@@ -723,9 +723,10 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
723
723
|
kind: "already-terminal";
|
|
724
724
|
request: {
|
|
725
725
|
readonly id: string;
|
|
726
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
726
727
|
readonly result: {
|
|
727
728
|
readonly kind: "confirmed" | "already-terminal";
|
|
728
|
-
readonly status: "failed" | "
|
|
729
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
729
730
|
readonly completedAt: number;
|
|
730
731
|
readonly output: unknown;
|
|
731
732
|
readonly errorTag: string | null;
|
|
@@ -736,7 +737,6 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
736
737
|
readonly enteredAt: number;
|
|
737
738
|
readonly generation: string;
|
|
738
739
|
} | null;
|
|
739
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
740
740
|
readonly generation: string;
|
|
741
741
|
readonly runId: string;
|
|
742
742
|
readonly requestedAt: number;
|
|
@@ -764,9 +764,10 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
764
764
|
request: {
|
|
765
765
|
dispatchAttempts: number;
|
|
766
766
|
id: string;
|
|
767
|
+
operation: "resume" | "cancel" | "terminate";
|
|
767
768
|
result: {
|
|
768
769
|
readonly kind: "confirmed" | "already-terminal";
|
|
769
|
-
readonly status: "failed" | "
|
|
770
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
770
771
|
readonly completedAt: number;
|
|
771
772
|
readonly output: unknown;
|
|
772
773
|
readonly errorTag: string | null;
|
|
@@ -777,7 +778,6 @@ export declare const beginWorkflowControlDispatchInTransaction: (tx: Store, id:
|
|
|
777
778
|
readonly enteredAt: number;
|
|
778
779
|
readonly generation: string;
|
|
779
780
|
} | null;
|
|
780
|
-
operation: "resume" | "cancel" | "terminate";
|
|
781
781
|
generation: string;
|
|
782
782
|
runId: string;
|
|
783
783
|
requestedAt: number;
|
|
@@ -814,9 +814,10 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
814
814
|
kind: "settled";
|
|
815
815
|
request: {
|
|
816
816
|
readonly id: string;
|
|
817
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
817
818
|
readonly result: {
|
|
818
819
|
readonly kind: "confirmed" | "already-terminal";
|
|
819
|
-
readonly status: "failed" | "
|
|
820
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
820
821
|
readonly completedAt: number;
|
|
821
822
|
readonly output: unknown;
|
|
822
823
|
readonly errorTag: string | null;
|
|
@@ -827,7 +828,6 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
827
828
|
readonly enteredAt: number;
|
|
828
829
|
readonly generation: string;
|
|
829
830
|
} | null;
|
|
830
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
831
831
|
readonly generation: string;
|
|
832
832
|
readonly runId: string;
|
|
833
833
|
readonly requestedAt: number;
|
|
@@ -853,9 +853,10 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
853
853
|
kind: "unknown";
|
|
854
854
|
request: {
|
|
855
855
|
readonly id: string;
|
|
856
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
856
857
|
readonly result: {
|
|
857
858
|
readonly kind: "confirmed" | "already-terminal";
|
|
858
|
-
readonly status: "failed" | "
|
|
859
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
859
860
|
readonly completedAt: number;
|
|
860
861
|
readonly output: unknown;
|
|
861
862
|
readonly errorTag: string | null;
|
|
@@ -866,7 +867,6 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
866
867
|
readonly enteredAt: number;
|
|
867
868
|
readonly generation: string;
|
|
868
869
|
} | null;
|
|
869
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
870
870
|
readonly generation: string;
|
|
871
871
|
readonly runId: string;
|
|
872
872
|
readonly requestedAt: number;
|
|
@@ -892,9 +892,10 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
892
892
|
kind: "superseded";
|
|
893
893
|
request: {
|
|
894
894
|
readonly id: string;
|
|
895
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
895
896
|
readonly result: {
|
|
896
897
|
readonly kind: "confirmed" | "already-terminal";
|
|
897
|
-
readonly status: "failed" | "
|
|
898
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
898
899
|
readonly completedAt: number;
|
|
899
900
|
readonly output: unknown;
|
|
900
901
|
readonly errorTag: string | null;
|
|
@@ -905,7 +906,6 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
905
906
|
readonly enteredAt: number;
|
|
906
907
|
readonly generation: string;
|
|
907
908
|
} | null;
|
|
908
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
909
909
|
readonly generation: string;
|
|
910
910
|
readonly runId: string;
|
|
911
911
|
readonly requestedAt: number;
|
|
@@ -931,9 +931,10 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
931
931
|
kind: "not-suspended";
|
|
932
932
|
request: {
|
|
933
933
|
readonly id: string;
|
|
934
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
934
935
|
readonly result: {
|
|
935
936
|
readonly kind: "confirmed" | "already-terminal";
|
|
936
|
-
readonly status: "failed" | "
|
|
937
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
937
938
|
readonly completedAt: number;
|
|
938
939
|
readonly output: unknown;
|
|
939
940
|
readonly errorTag: string | null;
|
|
@@ -944,7 +945,6 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
944
945
|
readonly enteredAt: number;
|
|
945
946
|
readonly generation: string;
|
|
946
947
|
} | null;
|
|
947
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
948
948
|
readonly generation: string;
|
|
949
949
|
readonly runId: string;
|
|
950
950
|
readonly requestedAt: number;
|
|
@@ -970,9 +970,10 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
970
970
|
kind: "bound";
|
|
971
971
|
request: {
|
|
972
972
|
readonly id: string;
|
|
973
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
973
974
|
readonly result: {
|
|
974
975
|
readonly kind: "confirmed" | "already-terminal";
|
|
975
|
-
readonly status: "failed" | "
|
|
976
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
976
977
|
readonly completedAt: number;
|
|
977
978
|
readonly output: unknown;
|
|
978
979
|
readonly errorTag: string | null;
|
|
@@ -983,7 +984,6 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
983
984
|
readonly enteredAt: number;
|
|
984
985
|
readonly generation: string;
|
|
985
986
|
} | null;
|
|
986
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
987
987
|
readonly generation: string;
|
|
988
988
|
readonly runId: string;
|
|
989
989
|
readonly requestedAt: number;
|
|
@@ -1009,9 +1009,10 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
1009
1009
|
kind: "waiting-journal";
|
|
1010
1010
|
request: {
|
|
1011
1011
|
readonly id: string;
|
|
1012
|
+
readonly operation: "resume" | "cancel" | "terminate";
|
|
1012
1013
|
readonly result: {
|
|
1013
1014
|
readonly kind: "confirmed" | "already-terminal";
|
|
1014
|
-
readonly status: "failed" | "
|
|
1015
|
+
readonly status: "failed" | "succeeded" | "cancelled";
|
|
1015
1016
|
readonly completedAt: number;
|
|
1016
1017
|
readonly output: unknown;
|
|
1017
1018
|
readonly errorTag: string | null;
|
|
@@ -1022,7 +1023,6 @@ export declare const bindWorkflowResumeJournalInTransaction: (tx: Store, id: str
|
|
|
1022
1023
|
readonly enteredAt: number;
|
|
1023
1024
|
readonly generation: string;
|
|
1024
1025
|
} | null;
|
|
1025
|
-
readonly operation: "resume" | "cancel" | "terminate";
|
|
1026
1026
|
readonly generation: string;
|
|
1027
1027
|
readonly runId: string;
|
|
1028
1028
|
readonly requestedAt: number;
|
|
@@ -1961,6 +1961,11 @@ export declare const isWorkflowEncrypted: (name: string) => boolean;
|
|
|
1961
1961
|
|
|
1962
1962
|
export declare const isWorkflowWorkerLayer: (value: unknown) => value is WorkflowWorkerLayerBrand;
|
|
1963
1963
|
|
|
1964
|
+
export declare interface JournalRoutingState {
|
|
1965
|
+
readonly generation: number;
|
|
1966
|
+
readonly layout: string;
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1964
1969
|
/**
|
|
1965
1970
|
* Attach the engine's execution id to the ledger row written by
|
|
1966
1971
|
* {@link admitStart}.
|
|
@@ -4159,6 +4164,17 @@ declare type WorkflowFn = <const Name extends string, Payload extends WorkflowPa
|
|
|
4159
4164
|
readonly name: Name;
|
|
4160
4165
|
} & WorkflowMessagesCarrier<NormaliseWorkflowMessages<Messages>>;
|
|
4161
4166
|
|
|
4167
|
+
/** Journal routing generation per PostgreSQL journal namespace. Declared, so the
|
|
4168
|
+
* schema owns it (plan, fingerprint, backup); the maintenance transition only
|
|
4169
|
+
* reads and writes it inside its pinned journal transaction. */
|
|
4170
|
+
export declare const workflowJournalRoutingTable: Table<"_voltro_workflow_journal_routing", FieldDefinitions<{
|
|
4171
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
4172
|
+
readonly namespace: ColumnBuilder<string, "text", boolean>;
|
|
4173
|
+
readonly generation: ColumnBuilder<string, "bigint", boolean>;
|
|
4174
|
+
readonly layout: ColumnBuilder<string, "text", boolean>;
|
|
4175
|
+
readonly relocation: ColumnBuilder<string, "text", boolean>;
|
|
4176
|
+
}>, false, never>;
|
|
4177
|
+
|
|
4162
4178
|
declare type WorkflowMake = typeof workflowModule.make;
|
|
4163
4179
|
|
|
4164
4180
|
export declare interface WorkflowMessagePairSchemas {
|
|
@@ -4584,6 +4600,15 @@ export declare type WorkflowScheduleOverlap = 'skip' | 'buffer' | 'cancelOther';
|
|
|
4584
4600
|
* that crossed a bundler boundary, and symbols do not survive every one. */
|
|
4585
4601
|
export declare const WorkflowScheduleProperty = "__voltroWorkflowSchedule";
|
|
4586
4602
|
|
|
4603
|
+
/** Explicit routing inventory shared by every runner in one cluster. Changing
|
|
4604
|
+
* groups changes persistent addresses; this is not a journal migration. */
|
|
4605
|
+
/** Group names are at most 32 ASCII characters: group + colon + a safe integer
|
|
4606
|
+
* slot fits the existing SQL journal shard_id VARCHAR(50) on every dialect. */
|
|
4607
|
+
export declare interface WorkflowShardGroups {
|
|
4608
|
+
readonly available: ReadonlyArray<string>;
|
|
4609
|
+
readonly assigned: ReadonlyArray<string>;
|
|
4610
|
+
}
|
|
4611
|
+
|
|
4587
4612
|
/**
|
|
4588
4613
|
* At most one run per key. The newcomer either stands down or evicts.
|
|
4589
4614
|
*
|
package/dist/index.js
CHANGED
|
@@ -24,26 +24,27 @@ import { stageWorkflowParentClosureInTransaction as kt } from "./parentClosure.j
|
|
|
24
24
|
import { readWorkflowRestartObservationInTransaction as At, reserveWorkflowRestartInTransaction as jt, withdrawWorkflowRestartInTransaction as Mt, workflowRestartRequestsTable as Nt, workflowRestartWithdrawalsTable as Pt } from "./workflowRestartReservation.js";
|
|
25
25
|
import { cancelSuspendedWorkflowRunInTransaction as Ft, completeWorkflowRunGenerationInTransaction as It, enterWorkflowRunGenerationInTransaction as Lt } from "./runGeneration.js";
|
|
26
26
|
import { queuedCancellationRequestsTable as Rt } from "./queuedCancellationRequest.js";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
|
|
27
|
+
import { workflowJournalRoutingTable as zt } from "./journalRoutingTable.js";
|
|
28
|
+
import { cancelQueuedWorkflowStartInTransaction as Bt, readQueuedWorkflowCancellationInTransaction as Vt } from "./queuedControl.js";
|
|
29
|
+
import { inspectAdmissionSubmissionRetry as Ht, retryAdmissionSubmissionInTransaction as Ut } from "./submissionRetry.js";
|
|
30
|
+
import { takeAdmittedSubmissionInTransaction as Wt, takePendingAdmissionSubmission as Gt } from "./pendingSubmission.js";
|
|
31
|
+
import { admitStart as Kt, linkExecution as qt } from "./admissionGate.js";
|
|
32
|
+
import { _voltroWorkflowWatermarksTable as Jt } from "./watermarkTable.js";
|
|
33
|
+
import { newestEventAt as Yt, planCancellations as Xt } from "./cancelOnPlan.js";
|
|
34
|
+
import { CANCEL_ON_WATERMARK as Zt, DEFAULT_COLD_LOOKBACK_MS as Qt, DEFAULT_EVENT_BATCH as $t, EVENTS_TABLE as en, WATERMARKS_TABLE as tn, readWatermark as nn, sweepCancelOn as rn, writeWatermark as an } from "./cancelOnSweep.js";
|
|
35
|
+
import { DEFAULT_STALL_AFTER_MS as on, DEFAULT_STALL_EVENT_LOOKBACK as sn, DEFAULT_STALL_RUN_PAGE as cn, sweepStalledRuns as ln } from "./stalenessSweep.js";
|
|
36
|
+
import { CLUSTER_REREAD_WINDOW_MS as un, ClusterDiagnostics as dn, describeStalledRun as fn } from "./clusterDiagnostics.js";
|
|
37
|
+
import { DEFAULT_DRAIN_BATCH as pn, acceptAdmissionSubmission as mn, drainTick as hn, isUnacknowledgedSubmission as gn } from "./admissionDrainer.js";
|
|
38
|
+
import { DEFAULT_SUSPEND_HINT_MS as _n, maybeHintSuspendingSignal as vn, resetSuspendHintsForTest as yn, resolveSuspendHintMs as bn, setSuspendSignalHintMs as xn } from "./signalHint.js";
|
|
39
|
+
import { awaitSignal as Sn } from "./signals.js";
|
|
40
|
+
import { awaitEvent as Cn } from "./awaitEvent.js";
|
|
41
|
+
import { SuspensionUnavailable as wn, WorkflowCannotPark as Tn } from "./suspensionUnavailable.js";
|
|
42
|
+
import { makeWorkflowUpdateId as En, resolveWorkflowMessageRun as Dn, sendWorkflowSignal as On, sendWorkflowUpdate as kn } from "./messages.js";
|
|
43
|
+
import { awaitSignalSuspending as An, completeSuspendingSignal as jn, suspendingSignalDeferredName as Mn } from "./signalsSuspending.js";
|
|
44
|
+
import { BUDGET_HOLDS_TABLE as Nn, BudgetHoldExpired as Pn, DEFAULT_BUDGET_HOLD_TIMEOUT_MS as Fn, _voltroBudgetHoldsTable as In, budgetHoldGeneration as Ln, budgetHoldKey as Rn, budgetHoldSignalName as zn, heldBudgets as Bn, pendingBudgetHolds as Vn, releaseBudgetHolds as Hn, suspendForBudget as Un } from "./budgetHold.js";
|
|
45
|
+
import { awaitUpdate as Wn } from "./updates.js";
|
|
46
|
+
import { inspectWorkflow as Gn } from "./inspectWorkflow.js";
|
|
47
|
+
import { makeInMemoryRecorder as Kn } from "./inMemoryRecorder.js";
|
|
48
|
+
import { DEFAULT_MAX_RUN_RECLAIMS as qn, DEFAULT_REPLAY_SHAPE_LIMIT as Jn, makeWorkflowRunRecorder as Yn, normaliseWorkflowPatches as Xn, resolveRunGuardTuning as Zn, serialiseWorkflowRowForWire as Qn, truncateWorkflowValue as $n, wrapWorkflowExecuteWithRunRecording as er } from "./runRecording.js";
|
|
49
|
+
import { recordWorkflowExecutionRefusal as tr } from "./executionRefusal.js";
|
|
50
|
+
export { et as ADMISSIONS_TABLE, Ie as ADMISSION_SUBMISSION_ID_PREFIX, Nn as BUDGET_HOLDS_TABLE, Pn as BudgetHoldExpired, Zt as CANCEL_ON_WATERMARK, un as CLUSTER_REREAD_WINDOW_MS, dn as ClusterDiagnostics, C as CurrentWorkflowExecutionId, w as CurrentWorkflowPatches, I as CurrentWorkflowReplayShape, T as CurrentWorkflowRunId, E as CurrentWorkflowStep, Fn as DEFAULT_BUDGET_HOLD_TIMEOUT_MS, Qt as DEFAULT_COLD_LOOKBACK_MS, pn as DEFAULT_DRAIN_BATCH, $t as DEFAULT_EVENT_BATCH, tt as DEFAULT_LEASE_MS, qn as DEFAULT_MAX_RUN_RECLAIMS, Jn as DEFAULT_REPLAY_SHAPE_LIMIT, on as DEFAULT_STALL_AFTER_MS, sn as DEFAULT_STALL_EVENT_LOOKBACK, cn as DEFAULT_STALL_RUN_PAGE, _n as DEFAULT_SUSPEND_HINT_MS, M as DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS, _ as DEFERRING_CONTROLS, en as EVENTS_TABLE, we as FlowControlKeyError, nt as PAUSES_TABLE, rt as PENDING_TABLE, i as STEP_JOURNAL_BINDING, Le as SUBMISSIONS_TABLE, wn as SuspensionUnavailable, tn as WATERMARKS_TABLE, a as WORKFLOW_JOURNAL_BINDING, Tn as WorkflowCannotPark, B as WorkflowFlowControlProperty, V as WorkflowMessagesProperty, D as WorkflowRunRecorder, N as WorkflowScheduleProperty, Je as WorkflowStartRequestConflictError, O as WorkflowStepInterceptorTag, H as WorkflowVersionTypeId, U as WorkflowWorkerLayerTypeId, In as _voltroBudgetHoldsTable, me as _voltroWorkflowAdmissionLocksTable, he as _voltroWorkflowAdmissionsTable, ge as _voltroWorkflowControlRequestsTable, _e as _voltroWorkflowFailureReportsTable, ve as _voltroWorkflowParentClosuresTable, ye as _voltroWorkflowPausesTable, be as _voltroWorkflowPendingTable, fe as _voltroWorkflowRunEventsTable, de as _voltroWorkflowRunStepsTable, ue as _voltroWorkflowRunsTable, pe as _voltroWorkflowStartContextsTable, xe as _voltroWorkflowStartReceiptsTable, Se as _voltroWorkflowSubmissionsTable, Jt as _voltroWorkflowWatermarksTable, mn as acceptAdmissionSubmission, Tt as acceptWorkflowControlInTransaction, Re as acknowledgeAdmissionSubmission, it as admissionLeaseHeldPredicate, Kt as admitStart, at as allIntents, v as assertConsistentPools, t as attachPreparedWorkflowExecution, Cn as awaitEvent, Sn as awaitSignal, An as awaitSignalSuspending, Wn as awaitUpdate, ze as beginAdmissionSubmissionDispatchInTransaction, Et as beginWorkflowControlDispatchInTransaction, Dt as bindWorkflowResumeJournalInTransaction, Ye as bindWorkflowStartReceipts, Ln as budgetHoldGeneration, Rn as budgetHoldKey, zn as budgetHoldSignalName, Bt as cancelQueuedWorkflowStartInTransaction, Ft as cancelSuspendedWorkflowRunInTransaction, Te as comparePendingOrder, jn as completeSuspendingSignal, It as completeWorkflowRunGenerationInTransaction, k as currentWorkflowStep, ot as deadLetterIntent, Ee as decideAdmission, y as deferringControlsOf, st as deleteIntent, fn as describeStalledRun, ct as discardIntent, lt as discardIntentInTransaction, hn as drainTick, ut as dueIntents, W as durableClock, G as durableQueue, K as durableQueueModule, Lt as enterWorkflowRunGenerationInTransaction, dt as evaluateAdmission, n as executePreparedWorkflow, e as failureMessage, A as getCurrentWorkflowExecutionId, j as getCurrentWorkflowRunId, q as getWorkflowFlowControl, o as getWorkflowJournalCipher, P as getWorkflowSchedule, J as getWorkflowVersionMetadata, Pe as handoffWorkflowFailureInTransaction, b as hasCancelOn, x as hasFlowControl, r as hasPreparedWorkflowExecution, Bn as heldBudgets, le as inMemoryWorkflowEngineLayer, Ht as inspectAdmissionSubmissionRetry, Gn as inspectWorkflow, Y as isCarrier, De as isFinishExpired, s as isSealedJournalValue, Oe as isStartExpired, gn as isUnacknowledgedSubmission, c as isWorkflowEncrypted, X as isWorkflowWorkerLayer, qt as linkExecution, Kn as makeInMemoryRecorder, L as makeReplayShapeTracker, Yn as makeWorkflowRunRecorder, En as makeWorkflowUpdateId, vn as maybeHintSuspendingSignal, Be as newAdmissionSubmissionId, Yt as newestEventAt, ke as nextSlotAt, R as nondeterminismEventPayload, Xn as normaliseWorkflowPatches, Ve as noteAdmissionSubmissionFailure, ft as noteIntentAttempt, l as openErrorText, u as openEventPayload, d as openJournalValue, f as openPayloadFields, p as openWorkflowRow, pt as parkDelayedStart, Z as patch, mt as pauseWorkflow, He as pendingAdmissionSubmissions, Vn as pendingBudgetHolds, ht as pendingSlotId, gt as pendingWindow, _t as persistDefer, Xt as planCancellations, Ae as pooledConcurrencyKey, Ue as prepareAdmissionSubmissionExecutionInTransaction, Q as processQueue, vt as pruneAdmissions, $ as queueWorker, Rt as queuedCancellationRequestsTable, ee as rateLimit, yt as readAdmissionState, We as readAdmissionSubmission, bt as readPausedWorkflows, Vt as readQueuedWorkflowCancellationInTransaction, nn as readWatermark, Ot as readWorkflowControlInTransaction, Me as readWorkflowFailureRecord, At as readWorkflowRestartObservationInTransaction, Xe as readWorkflowStartReceipt, Ze as readWorkflowStartRequest, Fe as reconcileWorkflowFailureInTransaction, xt as recordAdmission, tr as recordWorkflowExecutionRefusal, Ne as recordWorkflowFailureInTransaction, Qe as recordWorkflowStartReceipt, Ge as rejectAdmissionSubmissionInTransaction, Hn as releaseBudgetHolds, St as releaseLease, z as reportNondeterminism, Ke as reserveAdmissionSubmission, qe as reserveAdmissionSubmissionInTransaction, jt as reserveWorkflowRestartInTransaction, yn as resetSuspendHintsForTest, je as resolveAdmissionKeys, Zn as resolveRunGuardTuning, bn as resolveSuspendHintMs, Dn as resolveWorkflowMessageRun, $e as resolveWorkflowStartReceipt, Ct as resumeWorkflow, Ut as retryAdmissionSubmissionInTransaction, wt as retryDeadLetterIntent, m as sealJournalValue, On as sendWorkflowSignal, kn as sendWorkflowUpdate, Qn as serialiseWorkflowRowForWire, xn as setSuspendSignalHintMs, h as setWorkflowJournalCipher, te as sleep, ne as sleepUntil, kt as stageWorkflowParentClosureInTransaction, re as step, ie as stepIdempotencyKey, ae as stepModule, Un as suspendForBudget, Mn as suspendingSignalDeferredName, rn as sweepCancelOn, ln as sweepStalledRuns, Wt as takeAdmittedSubmissionInTransaction, Gt as takePendingAdmissionSubmission, $n as truncateWorkflowValue, g as tryOpenJournalValue, S as validateFlowControl, F as validateWorkflowSchedule, Ce as withAdmissionTransaction, oe as withCompensation, Mt as withdrawWorkflowRestartInTransaction, se as workflow, zt as workflowJournalRoutingTable, ce as workflowModule, Nt as workflowRestartRequestsTable, Pt as workflowRestartWithdrawalsTable, er as wrapWorkflowExecuteWithRunRecording, an as writeWatermark };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Context as e, Deferred as t, Effect as n, Option as r, Schedule as i, Semaphore as a } from "effect";
|
|
2
|
+
//#region src/journalRoutingGuard.ts
|
|
3
|
+
var o = (e) => n.gen(function* () {
|
|
4
|
+
let r = e.pollMs ?? 1e3, o = e.verify;
|
|
5
|
+
if (!Number.isSafeInteger(r) || r < 1 || r > 3e4) return yield* n.fail(/* @__PURE__ */ Error("Invalid journal routing probe interval"));
|
|
6
|
+
let s = yield* t.make(), c = /* @__PURE__ */ new Set(), l = yield* a.make(1), u = !1, d = (e) => n.gen(function* () {
|
|
7
|
+
u = !0, yield* t.fail(s, Error(e));
|
|
8
|
+
}), f = l.withPermits(1)(n.gen(function* () {
|
|
9
|
+
if (u) return yield* t.await(s);
|
|
10
|
+
let e = yield* n.interruptible(o).pipe(n.timeout(r), n.isSuccess);
|
|
11
|
+
if (u) return yield* t.await(s);
|
|
12
|
+
if (!e) return yield* d("Journal routing lock ownership was lost"), yield* t.await(s);
|
|
13
|
+
})), p = (e) => n.uninterruptibleMask((r) => n.gen(function* () {
|
|
14
|
+
if (u) return yield* t.await(s);
|
|
15
|
+
let i = yield* t.make();
|
|
16
|
+
return c.add(i), yield* r(f.pipe(n.andThen(n.suspend(() => u ? t.await(s) : n.raceFirst(e, n.interruptible(t.await(s))))))).pipe(n.ensuring(n.gen(function* () {
|
|
17
|
+
c.delete(i), yield* t.succeed(i, void 0);
|
|
18
|
+
})));
|
|
19
|
+
})), m = (e) => n.uninterruptibleMask((r) => n.gen(function* () {
|
|
20
|
+
if (u) return yield* t.await(s);
|
|
21
|
+
let i = yield* t.make();
|
|
22
|
+
c.add(i);
|
|
23
|
+
let a = new AbortController(), o = Promise.resolve().then(() => {
|
|
24
|
+
if (u) throw Error("Journal routing admission is closed");
|
|
25
|
+
return e(a.signal);
|
|
26
|
+
});
|
|
27
|
+
return yield* r(n.tryPromise({
|
|
28
|
+
try: () => o,
|
|
29
|
+
catch: (e) => e
|
|
30
|
+
})).pipe(n.ensuring(n.gen(function* () {
|
|
31
|
+
a.abort(), yield* n.promise(() => o.then(() => void 0, () => void 0)), c.delete(i), yield* t.succeed(i, void 0);
|
|
32
|
+
})));
|
|
33
|
+
})), h = n.gen(function* () {
|
|
34
|
+
yield* d("Journal routing admission is closed"), yield* n.forEach([...c], (e) => t.await(e), { discard: !0 });
|
|
35
|
+
});
|
|
36
|
+
return yield* n.addFinalizer(() => h), yield* f.pipe(n.ignore, n.repeat(i.spaced(r)), n.forkScoped), {
|
|
37
|
+
run: p,
|
|
38
|
+
ownPromise: m,
|
|
39
|
+
check: f,
|
|
40
|
+
close: h,
|
|
41
|
+
isClosed: () => u
|
|
42
|
+
};
|
|
43
|
+
}), s = e.Service("@voltro/workflow/JournalRoutingGuard"), c = (e, t) => e === void 0 ? t : n.gen(function* () {
|
|
44
|
+
return yield* yield* e.run(n.exit(t.pipe(n.provideService(s, e)))).pipe(n.orDie);
|
|
45
|
+
}), l = (e) => n.flatMap(n.serviceOption(s), (t) => r.isSome(t) ? t.value.ownPromise(e).pipe(n.orDie) : n.promise(e)), u = (e) => n.flatMap(n.serviceOption(s), (t) => r.isSome(t) ? t.value.ownPromise(e) : n.tryPromise({
|
|
46
|
+
try: e,
|
|
47
|
+
catch: (e) => e
|
|
48
|
+
}));
|
|
49
|
+
//#endregion
|
|
50
|
+
export { s as JournalRoutingGuard, o as makeJournalRoutingGuard, l as ownedJournalRoutingPromise, c as protectJournalRoutingEffect, u as tryOwnedJournalRoutingPromise };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/journalRoutingLayout.ts
|
|
2
|
+
var e = (e) => {
|
|
3
|
+
if (e !== "default" && e !== "api-workloads-v1") throw Error("Unknown journal routing layout");
|
|
4
|
+
let t = e === "api-workloads-v1";
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
id: e,
|
|
7
|
+
workflowGroup: "default",
|
|
8
|
+
webhookGroup: t ? "voltro.webhooks" : "default",
|
|
9
|
+
cronGroup: t ? "voltro.schedules" : "default",
|
|
10
|
+
available: Object.freeze(t ? [
|
|
11
|
+
"default",
|
|
12
|
+
"voltro.webhooks",
|
|
13
|
+
"voltro.schedules"
|
|
14
|
+
] : ["default"])
|
|
15
|
+
});
|
|
16
|
+
}, t = (t, n) => {
|
|
17
|
+
let r = e(t), i = e(n), a = [];
|
|
18
|
+
return r.webhookGroup !== i.webhookGroup && a.push({
|
|
19
|
+
entity: "workflow",
|
|
20
|
+
name: "voltro.deliverWebhook",
|
|
21
|
+
from: r.webhookGroup,
|
|
22
|
+
to: i.webhookGroup
|
|
23
|
+
}), r.cronGroup !== i.cronGroup && a.push({
|
|
24
|
+
entity: "cron",
|
|
25
|
+
name: "*",
|
|
26
|
+
from: r.cronGroup,
|
|
27
|
+
to: i.cronGroup
|
|
28
|
+
}), Object.freeze(a.map((e) => Object.freeze(e)));
|
|
29
|
+
}, n = (t, n) => {
|
|
30
|
+
let r = e(t);
|
|
31
|
+
return n === "voltro.deliverWebhook" ? r.webhookGroup : r.workflowGroup;
|
|
32
|
+
}, r = (t, n) => {
|
|
33
|
+
let r = e(t), i = [
|
|
34
|
+
n.workflows,
|
|
35
|
+
n.schedules,
|
|
36
|
+
n.webhooks
|
|
37
|
+
];
|
|
38
|
+
if (i.some((e) => typeof e != "boolean")) throw Error("Explicit executor selection is required");
|
|
39
|
+
if (t === "default" && i.some(Boolean) && !i.every(Boolean)) throw Error("Separate executor roles require the api-workloads-v1 journal routing transition");
|
|
40
|
+
let a = /* @__PURE__ */ new Set();
|
|
41
|
+
return n.workflows && a.add(r.workflowGroup), n.schedules && a.add(r.cronGroup), n.webhooks && a.add(r.webhookGroup), Object.freeze({
|
|
42
|
+
available: r.available,
|
|
43
|
+
assigned: Object.freeze([...a])
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { r as journalExecutorGroups, e as journalRoutingLayout, t as journalRoutingTransitions, n as journalWorkflowGroup };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Effect as e } from "effect";
|
|
2
|
+
import { SqlClient as t } from "effect/sql";
|
|
3
|
+
import { fnv1a64 as n } from "@voltro/database/sql";
|
|
4
|
+
//#region src/journalRoutingLock.ts
|
|
5
|
+
var r = (r) => e.gen(function* () {
|
|
6
|
+
let i = r.namespace, a = r.mode, o = r.timeoutMs ?? 3e4;
|
|
7
|
+
if (!i || i.length > 256 || !["shared", "exclusive"].includes(a) || !Number.isSafeInteger(o) || o < 1 || o > 3e5) return yield* e.fail(/* @__PURE__ */ Error("Invalid journal routing lock options"));
|
|
8
|
+
let s = yield* t.SqlClient, c = s.onDialectOrElse({
|
|
9
|
+
pg: () => "pg",
|
|
10
|
+
mssql: () => "mssql",
|
|
11
|
+
orElse: () => "unsupported"
|
|
12
|
+
});
|
|
13
|
+
if (c === "unsupported") return yield* e.fail(/* @__PURE__ */ Error("Journal routing locks require PostgreSQL or SQL Server"));
|
|
14
|
+
let l = (n("voltro:journal-routing:" + i) & 9223372036854775807n).toString(), u = "voltro-journal-routing-" + l, d = yield* s.reserve, f = a === "shared" ? "_shared" : "", p = c === "pg" ? `SELECT pg_try_advisory_lock${f}(${l}::bigint)` : `DECLARE @res int; EXEC @res = sp_getapplock @Resource = '${u}', @LockMode = '${a === "shared" ? "Shared" : "Exclusive"}', @LockOwner = 'Session', @LockTimeout = 0; SELECT @res`, m = c === "pg" ? `SELECT pg_advisory_unlock${f}(${l}::bigint)` : `DECLARE @res int; EXEC @res = sp_releaseapplock @Resource = '${u}', @LockOwner = 'Session'; SELECT @res`, h = performance.now(), g = e.gen(function* () {
|
|
15
|
+
for (;;) {
|
|
16
|
+
let t = (yield* d.executeValues(p, []))[0]?.[0];
|
|
17
|
+
if (c === "pg" ? t === !0 || t === "t" || t === 1 : typeof t == "number" && t >= 0) return;
|
|
18
|
+
if (c === "mssql" && t !== -1) return yield* e.fail(/* @__PURE__ */ Error("Journal routing application lock failed"));
|
|
19
|
+
let n = o - (performance.now() - h);
|
|
20
|
+
if (n <= 0) return yield* e.fail(/* @__PURE__ */ Error("Journal routing lock acquisition timed out"));
|
|
21
|
+
yield* e.sleep(Math.min(n, 100));
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
yield* e.acquireRelease(g, () => d.executeValues(m, []).pipe(e.flatMap((t) => {
|
|
25
|
+
let n = t[0]?.[0];
|
|
26
|
+
return (c === "pg" ? n === !0 || n === "t" || n === 1 : typeof n == "number" && n >= 0) ? e.void : e.die(/* @__PURE__ */ Error("Journal routing lock was lost before release"));
|
|
27
|
+
}), e.orDie));
|
|
28
|
+
let _ = c === "pg" ? `SELECT EXISTS (SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND pid = pg_backend_pid() AND granted AND classid = (${l}::bigint >> 32)::oid AND objid = (${l}::bigint & 4294967295)::oid AND objsubid = 1 AND mode = '${a === "shared" ? "ShareLock" : "ExclusiveLock"}')` : `SELECT APPLOCK_MODE('public', '${u}', 'Session')`;
|
|
29
|
+
return {
|
|
30
|
+
connection: d,
|
|
31
|
+
dialect: c,
|
|
32
|
+
verify: d.executeValues(_, []).pipe(e.flatMap((t) => {
|
|
33
|
+
let n = t[0]?.[0];
|
|
34
|
+
return (c === "pg" ? n === !0 || n === "t" || n === 1 : n === (a === "shared" ? "Shared" : "Exclusive")) ? e.void : e.fail(/* @__PURE__ */ Error("Journal routing lock ownership was lost"));
|
|
35
|
+
}))
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
export { r as acquireJournalRoutingLock };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { withJournalRoutingTransaction as e } from "./journalRoutingTransaction.js";
|
|
2
|
+
import { acquireJournalRoutingLock as t } from "./journalRoutingLock.js";
|
|
3
|
+
import { JournalRoutingMaintenance as n } from "./workflowShardRelocationSql.js";
|
|
4
|
+
import { Effect as r, Option as i } from "effect";
|
|
5
|
+
import { SqlClient as a } from "effect/sql";
|
|
6
|
+
//#region src/journalRoutingMaintenance.ts
|
|
7
|
+
var o = (o, s = 3e4) => r.gen(function* () {
|
|
8
|
+
let c = yield* a.SqlClient;
|
|
9
|
+
return c.onDialectOrElse({
|
|
10
|
+
pg: () => !0,
|
|
11
|
+
orElse: () => !1
|
|
12
|
+
}) ? n.of({ exclusive: (n) => r.scoped(r.gen(function* () {
|
|
13
|
+
let a = yield* r.serviceOption(c.transactionService);
|
|
14
|
+
if (i.isSome(a)) return yield* r.fail(/* @__PURE__ */ Error("Journal maintenance cannot enter an ambient transaction"));
|
|
15
|
+
let { connection: l } = yield* t({
|
|
16
|
+
namespace: o,
|
|
17
|
+
mode: "exclusive",
|
|
18
|
+
timeoutMs: s
|
|
19
|
+
});
|
|
20
|
+
return yield* e(c, l, n);
|
|
21
|
+
})).pipe(r.provideService(a.SqlClient, c)) }) : yield* r.fail(/* @__PURE__ */ Error("Pinned journal maintenance currently requires PostgreSQL"));
|
|
22
|
+
});
|
|
23
|
+
//#endregion
|
|
24
|
+
export { o as makePostgresJournalRoutingMaintenance };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { protectJournalRoutingEffect as e } from "./journalRoutingGuard.js";
|
|
2
|
+
import { Effect as t } from "effect";
|
|
3
|
+
import { MessageStorage as n } from "effect/cluster";
|
|
4
|
+
import { PersistenceError as r } from "effect/cluster/ClusterError";
|
|
5
|
+
//#region src/journalRoutingMessageStorage.ts
|
|
6
|
+
var i = (i, a) => {
|
|
7
|
+
let o = (e) => t.gen(function* () {
|
|
8
|
+
return yield* yield* a.run(t.exit(e)).pipe(t.mapError((e) => new r({ cause: e })));
|
|
9
|
+
});
|
|
10
|
+
return n.MessageStorage.of({
|
|
11
|
+
saveRequest: (e) => o(t.suspend(() => i.saveRequest(e))),
|
|
12
|
+
saveEnvelope: (e) => o(t.suspend(() => i.saveEnvelope(e))),
|
|
13
|
+
saveReply: (e) => o(t.suspend(() => i.saveReply(e))),
|
|
14
|
+
clearReplies: (e) => o(t.suspend(() => i.clearReplies(e))),
|
|
15
|
+
repliesFor: (e) => o(t.suspend(() => i.repliesFor(e))),
|
|
16
|
+
repliesForUnfiltered: (e) => o(t.suspend(() => i.repliesForUnfiltered(e))),
|
|
17
|
+
requestIdForPrimaryKey: (e) => o(t.suspend(() => i.requestIdForPrimaryKey(e))),
|
|
18
|
+
unprocessedMessages: (e) => o(t.suspend(() => i.unprocessedMessages(e))),
|
|
19
|
+
unprocessedMessagesById: (e) => o(t.suspend(() => i.unprocessedMessagesById(e))),
|
|
20
|
+
resetShards: (e) => o(t.suspend(() => i.resetShards(e))),
|
|
21
|
+
resetRequests: (e) => o(t.suspend(() => i.resetRequests(e))),
|
|
22
|
+
resetAddresses: (e) => o(t.suspend(() => i.resetAddresses(e))),
|
|
23
|
+
withTransaction: (t) => e(a, i.withTransaction(t)),
|
|
24
|
+
resetAddress: (e) => o(t.suspend(() => i.resetAddress(e))),
|
|
25
|
+
clearAddress: (e) => o(t.suspend(() => i.clearAddress(e))),
|
|
26
|
+
registerReplyHandler: (e) => i.registerReplyHandler(e),
|
|
27
|
+
unregisterReplyHandler: (e) => i.unregisterReplyHandler(e),
|
|
28
|
+
unregisterShardReplyHandlers: (e) => i.unregisterShardReplyHandlers(e)
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { i as guardJournalMessageStorage };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { workflowJournalRoutingTable as e } from "./journalRoutingTable.js";
|
|
2
|
+
import { Effect as t } from "effect";
|
|
3
|
+
import { SqlClient as n } from "effect/sql";
|
|
4
|
+
//#region src/journalRoutingNamespace.ts
|
|
5
|
+
var r = t.gen(function* () {
|
|
6
|
+
let r = (yield* n.SqlClient).withoutTransforms();
|
|
7
|
+
if (!r.onDialectOrElse({
|
|
8
|
+
pg: () => !0,
|
|
9
|
+
orElse: () => !1
|
|
10
|
+
})) return yield* t.fail(/* @__PURE__ */ Error("Journal namespace resolution requires PostgreSQL"));
|
|
11
|
+
let i = yield* r`
|
|
12
|
+
SELECT n.nspname AS schema_name, current_schema() AS active_schema, c.relkind AS kind,
|
|
13
|
+
format('%I.%I', n.nspname, ${e.tableName}::text) AS routing_table
|
|
14
|
+
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
15
|
+
WHERE c.oid = to_regclass('cluster_messages')`, a = i[0];
|
|
16
|
+
return i.length !== 1 || !a || a.kind !== "r" || a.schema_name !== a.active_schema ? yield* t.fail(/* @__PURE__ */ Error("Journal table must exist in the active PostgreSQL schema without search-path fallback")) : Object.freeze({
|
|
17
|
+
namespace: `pg:${a.schema_name}:cluster_messages`,
|
|
18
|
+
schema: a.schema_name,
|
|
19
|
+
routingTable: r.literal(a.routing_table)
|
|
20
|
+
});
|
|
21
|
+
}), i = r.pipe(t.map((e) => e.namespace));
|
|
22
|
+
//#endregion
|
|
23
|
+
export { r as resolvePostgresJournalLocation, i as resolvePostgresJournalNamespace };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { journalRoutingLayout as e, journalWorkflowGroup as t } from "./journalRoutingLayout.js";
|
|
2
|
+
import { Context as n } from "effect";
|
|
3
|
+
import { ClusterSchema as r } from "effect/cluster";
|
|
4
|
+
//#region src/journalRoutingRuntime.ts
|
|
5
|
+
var i = class extends n.Service()("@voltro/workflow/JournalRoutingLayout") {}, a = (e, i) => {
|
|
6
|
+
let a = n.add(e.annotations, r.ShardGroup, () => t(i, e._tag));
|
|
7
|
+
return new Proxy(e, { get(e, t, n) {
|
|
8
|
+
return t === "annotations" ? a : Reflect.get(e, t, n);
|
|
9
|
+
} });
|
|
10
|
+
}, o = (t, n) => (e(n), {
|
|
11
|
+
...t,
|
|
12
|
+
register: (e, r) => t.register(a(e, n), r),
|
|
13
|
+
execute: (e, r) => t.execute(a(e, n), r),
|
|
14
|
+
poll: (e, r) => t.poll(a(e, n), r),
|
|
15
|
+
interrupt: (e, r) => t.interrupt(a(e, n), r),
|
|
16
|
+
resume: (e, r) => t.resume(a(e, n), r),
|
|
17
|
+
scheduleClock: (e, r) => t.scheduleClock(a(e, n), r)
|
|
18
|
+
}), s = (n, i) => {
|
|
19
|
+
let a = e(i), o = (e) => e.startsWith("Workflow/") && !e.startsWith("Workflow/-/") ? t(i, e.slice(9)) : e.startsWith("ClusterCron/") ? a.cronGroup : void 0;
|
|
20
|
+
return {
|
|
21
|
+
...n,
|
|
22
|
+
makeClient: (e) => {
|
|
23
|
+
let t = o(e.type);
|
|
24
|
+
return n.makeClient(t === void 0 ? e : e.annotate(r.ShardGroup, () => t));
|
|
25
|
+
},
|
|
26
|
+
registerEntity: (e, t, i) => {
|
|
27
|
+
let a = o(e.type);
|
|
28
|
+
return n.registerEntity(a === void 0 ? e : e.annotate(r.ShardGroup, () => a), t, i);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { i as JournalRoutingLayout, a as routeJournalWorkflow, s as withJournalEntityRouting, o as withJournalWorkflowRouting };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { protectJournalRoutingEffect as e } from "./journalRoutingGuard.js";
|
|
2
|
+
import { Effect as t, Stream as n } from "effect";
|
|
3
|
+
import { Rpc as r, RpcSchema as i } from "effect/rpc";
|
|
4
|
+
//#region src/journalRoutingSharding.ts
|
|
5
|
+
var a = (a, o) => {
|
|
6
|
+
let s = (i) => {
|
|
7
|
+
if (typeof i == "object" && i && r.isWrapper(i)) return {
|
|
8
|
+
...i,
|
|
9
|
+
value: s(i.value)
|
|
10
|
+
};
|
|
11
|
+
if (t.isEffect(i)) return e(o, i);
|
|
12
|
+
if (n.isStream(i)) {
|
|
13
|
+
let r = i;
|
|
14
|
+
return n.unwrap(t.map(e(o, n.toPull(r)), (r) => n.fromPull(t.succeed(e(o, r)))));
|
|
15
|
+
}
|
|
16
|
+
throw Error("Cluster handler must return an Effect, Stream or RPC wrapper");
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
...a,
|
|
20
|
+
registerEntity: (r, c, l) => e(o, t.suspend(() => a.registerEntity(r, c.pipe(t.map((e) => new Proxy(e, { get(e, a, c) {
|
|
21
|
+
let l = Reflect.get(e, a, c), u = typeof a == "string" ? r.protocol.requests.get(a) : void 0;
|
|
22
|
+
return !u || typeof l != "function" ? l : (...r) => o.isClosed() ? i.isStreamSchema(u.successSchema) ? n.fromEffect(t.interrupt) : t.interrupt : s(Reflect.apply(l, e, r));
|
|
23
|
+
} }))), l))),
|
|
24
|
+
registerSingleton: (n, r, i) => e(o, t.suspend(() => a.registerSingleton(n, e(o, r), i)))
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { a as withJournalRoutingGuard };
|