stitchkit 0.80.0 → 0.81.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/dist/agent-runtime/provider-failure.d.ts.map +1 -1
- package/dist/agent-runtime-coding-tools.js +1 -1
- package/dist/agent-runtime-harness.js +7 -5
- package/dist/agent-runtime.js +15 -19
- package/dist/application/notification-outbox.d.ts +80 -0
- package/dist/application/notification-outbox.d.ts.map +1 -0
- package/dist/application/process-lifecycle.d.ts +166 -0
- package/dist/application/process-lifecycle.d.ts.map +1 -0
- package/dist/application/revision-signal.d.ts +86 -0
- package/dist/application/revision-signal.d.ts.map +1 -0
- package/dist/application/state-store.d.ts +18 -0
- package/dist/application/state-store.d.ts.map +1 -0
- package/dist/application.d.ts +4 -0
- package/dist/application.d.ts.map +1 -1
- package/dist/application.js +725 -1
- package/dist/browser/http.d.ts +14 -0
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/resumable.d.ts +6 -0
- package/dist/browser/resumable.d.ts.map +1 -1
- package/dist/cli.js +9 -7
- package/dist/contract/define.d.ts +27 -4
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/errors-factory.d.ts +22 -3
- package/dist/contract/errors-factory.d.ts.map +1 -1
- package/dist/contract/index.d.ts +2 -2
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +1 -1
- package/dist/geo/index.d.ts +4 -0
- package/dist/geo/index.d.ts.map +1 -0
- package/dist/geo/maxmind.d.ts +4 -0
- package/dist/geo/maxmind.d.ts.map +1 -0
- package/dist/geo/resolver.d.ts +9 -0
- package/dist/geo/resolver.d.ts.map +1 -0
- package/dist/geo/types.d.ts +59 -0
- package/dist/geo/types.d.ts.map +1 -0
- package/dist/geo.d.ts +3 -0
- package/dist/geo.d.ts.map +1 -0
- package/dist/geo.js +245 -0
- package/dist/{index-9s6z8vgf.js → index-1dd82z59.js} +1 -1
- package/dist/{index-vwp69871.js → index-27487ay5.js} +4 -4
- package/dist/{index-7ag81v2f.js → index-27gm3d6g.js} +10 -321
- package/dist/{index-y01f4223.js → index-2bxcmqkb.js} +127 -43
- package/dist/{index-dxesg10d.js → index-3ds42w1w.js} +3 -3
- package/dist/index-3xwxfj4z.js +334 -0
- package/dist/{index-egaabxkz.js → index-5z8tezpx.js} +2 -2
- package/dist/{index-fxz0v7vg.js → index-7evdsyez.js} +1 -83
- package/dist/{index-xcetq6j3.js → index-90d7h2cr.js} +32 -13
- package/dist/{index-t0z5p5w6.js → index-apn8repm.js} +1 -1
- package/dist/{index-758zx2ha.js → index-dggwnnjv.js} +2 -2
- package/dist/{index-dwf1f2ap.js → index-f9mb610r.js} +1 -62
- package/dist/{index-5mtc969c.js → index-fwbkp2jn.js} +1 -1
- package/dist/index-p13mwz16.js +16 -0
- package/dist/{index-m9kzax52.js → index-p18f59zy.js} +21 -5
- package/dist/{index-hb5pf3s4.js → index-qmgs7y68.js} +1 -1
- package/dist/{index-2rwwmr7v.js → index-s4ckmrac.js} +1 -1
- package/dist/{index-h4pj6fta.js → index-s8cnx02s.js} +8 -5
- package/dist/{index-k9ay6v6d.js → index-vchzar7e.js} +74 -23
- package/dist/index-vsbzgd7b.js +84 -0
- package/dist/{index-dxjjv399.js → index-xbppf54a.js} +95 -15
- package/dist/index-y91ry9h2.js +4 -0
- package/dist/index-zcgf3gqf.js +83 -0
- package/dist/index.js +17 -13
- package/dist/internal/error-message.d.ts +3 -0
- package/dist/internal/error-message.d.ts.map +1 -0
- package/dist/internal/media-type.d.ts +8 -0
- package/dist/internal/media-type.d.ts.map +1 -0
- package/dist/internal/route-pattern.d.ts +21 -0
- package/dist/internal/route-pattern.d.ts.map +1 -1
- package/dist/node.js +9 -6
- package/dist/observability/audit.d.ts +28 -1
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/bounded-logger.d.ts +20 -0
- package/dist/observability/bounded-logger.d.ts.map +1 -0
- package/dist/observability/context.d.ts +12 -3
- package/dist/observability/context.d.ts.map +1 -1
- package/dist/observability/index.d.ts +3 -2
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +138 -8
- package/dist/observability/sanitize.d.ts +17 -0
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/primitives.js +1 -1
- package/dist/react/query-client.d.ts +33 -0
- package/dist/react/query-client.d.ts.map +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +83 -1
- package/dist/realtime/registry.d.ts +93 -0
- package/dist/realtime/registry.d.ts.map +1 -0
- package/dist/release/header.d.ts +9 -0
- package/dist/release/header.d.ts.map +1 -0
- package/dist/release/marker.d.ts +39 -0
- package/dist/release/marker.d.ts.map +1 -0
- package/dist/release/socket.d.ts +44 -0
- package/dist/release/socket.d.ts.map +1 -0
- package/dist/release/watcher.d.ts +66 -0
- package/dist/release/watcher.d.ts.map +1 -0
- package/dist/release.d.ts +15 -0
- package/dist/release.d.ts.map +1 -0
- package/dist/release.js +196 -0
- package/dist/remote.js +12 -7
- package/dist/server/context.d.ts +2 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +17 -16
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/file-state-store.d.ts +23 -0
- package/dist/server/file-state-store.d.ts.map +1 -0
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +469 -11
- package/dist/server/middleware/cookies.d.ts +33 -1
- package/dist/server/middleware/cookies.d.ts.map +1 -1
- package/dist/server/middleware/cors.d.ts +16 -1
- package/dist/server/middleware/cors.d.ts.map +1 -1
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/release-signal.d.ts +35 -0
- package/dist/server/release-signal.d.ts.map +1 -0
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/types.d.ts +26 -2
- package/dist/server/types.d.ts.map +1 -1
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/testing.js +7 -4
- package/dist/tool-invoker.js +8 -6
- package/dist/tools/download-core.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools.js +20 -16
- package/dist/tracking/attribution.d.ts +51 -0
- package/dist/tracking/attribution.d.ts.map +1 -0
- package/dist/tracking/beacon.d.ts +14 -0
- package/dist/tracking/beacon.d.ts.map +1 -0
- package/dist/tracking/clicks.d.ts +46 -0
- package/dist/tracking/clicks.d.ts.map +1 -0
- package/dist/tracking/client.d.ts +121 -0
- package/dist/tracking/client.d.ts.map +1 -0
- package/dist/tracking/contract.d.ts +46 -0
- package/dist/tracking/contract.d.ts.map +1 -0
- package/dist/tracking/delivery.d.ts +24 -0
- package/dist/tracking/delivery.d.ts.map +1 -0
- package/dist/tracking/host.d.ts +43 -0
- package/dist/tracking/host.d.ts.map +1 -0
- package/dist/tracking/once-per-page.d.ts +17 -0
- package/dist/tracking/once-per-page.d.ts.map +1 -0
- package/dist/tracking/outbox-storage-indexeddb.d.ts +12 -0
- package/dist/tracking/outbox-storage-indexeddb.d.ts.map +1 -0
- package/dist/tracking/outbox-storage-memory.d.ts +12 -0
- package/dist/tracking/outbox-storage-memory.d.ts.map +1 -0
- package/dist/tracking/outbox.d.ts +98 -0
- package/dist/tracking/outbox.d.ts.map +1 -0
- package/dist/tracking/schemas.d.ts +183 -0
- package/dist/tracking/schemas.d.ts.map +1 -0
- package/dist/tracking/scroll.d.ts +22 -0
- package/dist/tracking/scroll.d.ts.map +1 -0
- package/dist/tracking/sequence-reserve.d.ts +34 -0
- package/dist/tracking/sequence-reserve.d.ts.map +1 -0
- package/dist/tracking/server/active-interval.d.ts +26 -0
- package/dist/tracking/server/active-interval.d.ts.map +1 -0
- package/dist/tracking/server/bot.d.ts +9 -0
- package/dist/tracking/server/bot.d.ts.map +1 -0
- package/dist/tracking/server/disposition.d.ts +55 -0
- package/dist/tracking/server/disposition.d.ts.map +1 -0
- package/dist/tracking/server/hash.d.ts +13 -0
- package/dist/tracking/server/hash.d.ts.map +1 -0
- package/dist/tracking/server/presence.d.ts +27 -0
- package/dist/tracking/server/presence.d.ts.map +1 -0
- package/dist/tracking/server/visit-lease.d.ts +92 -0
- package/dist/tracking/server/visit-lease.d.ts.map +1 -0
- package/dist/tracking/visible-time.d.ts +38 -0
- package/dist/tracking/visible-time.d.ts.map +1 -0
- package/dist/tracking-server.d.ts +14 -0
- package/dist/tracking-server.d.ts.map +1 -0
- package/dist/tracking-server.js +173 -0
- package/dist/tracking.d.ts +24 -0
- package/dist/tracking.d.ts.map +1 -0
- package/dist/tracking.js +1090 -0
- package/llms-full.txt +986 -30
- package/llms.txt +4 -0
- package/package.json +26 -5
package/dist/application.js
CHANGED
|
@@ -62,8 +62,9 @@ import {
|
|
|
62
62
|
createBoundedSinkManager
|
|
63
63
|
} from "./index-a59da114.js";
|
|
64
64
|
import {
|
|
65
|
+
backoffDelay,
|
|
65
66
|
createBackoff
|
|
66
|
-
} from "./index-
|
|
67
|
+
} from "./index-s8cnx02s.js";
|
|
67
68
|
import {
|
|
68
69
|
watchKeyString
|
|
69
70
|
} from "./index-dre2ywck.js";
|
|
@@ -77,11 +78,15 @@ import {
|
|
|
77
78
|
createBoundedChannel,
|
|
78
79
|
createCreditWindow
|
|
79
80
|
} from "./index-7gnkny4z.js";
|
|
81
|
+
import {
|
|
82
|
+
measureSize
|
|
83
|
+
} from "./index-xbppf54a.js";
|
|
80
84
|
import {
|
|
81
85
|
argumentsDigest,
|
|
82
86
|
stableValue
|
|
83
87
|
} from "./index-a916km3r.js";
|
|
84
88
|
import"./index-0w9abg87.js";
|
|
89
|
+
import"./index-kzfs85xp.js";
|
|
85
90
|
import"./index-77fekveh.js";
|
|
86
91
|
// src/application/admission.ts
|
|
87
92
|
import { z } from "zod";
|
|
@@ -778,6 +783,707 @@ function sqliteKeyspaceBackend(declaration, config) {
|
|
|
778
783
|
}
|
|
779
784
|
};
|
|
780
785
|
}
|
|
786
|
+
// src/application/notification-outbox.ts
|
|
787
|
+
import { z as z5 } from "zod";
|
|
788
|
+
function notificationOutboxStateSchema(payload) {
|
|
789
|
+
return z5.object({
|
|
790
|
+
schemaVersion: z5.literal(1),
|
|
791
|
+
queue: z5.array(z5.object({
|
|
792
|
+
key: z5.string().min(1).max(512),
|
|
793
|
+
payload,
|
|
794
|
+
createdAt: z5.string().datetime({ offset: true }),
|
|
795
|
+
attempts: z5.number().int().nonnegative(),
|
|
796
|
+
nextAttemptAt: z5.string().datetime({ offset: true }),
|
|
797
|
+
leaseOwner: z5.string().min(1).max(128).nullable(),
|
|
798
|
+
leaseId: z5.string().min(1).max(128).nullable(),
|
|
799
|
+
leaseUntil: z5.string().datetime({ offset: true }).nullable()
|
|
800
|
+
}).strict()),
|
|
801
|
+
receipts: z5.array(z5.object({
|
|
802
|
+
key: z5.string().min(1).max(512),
|
|
803
|
+
completedAt: z5.string().datetime({ offset: true })
|
|
804
|
+
}).strict())
|
|
805
|
+
}).strict();
|
|
806
|
+
}
|
|
807
|
+
var emptyOutboxState = () => ({
|
|
808
|
+
schemaVersion: 1,
|
|
809
|
+
queue: [],
|
|
810
|
+
receipts: []
|
|
811
|
+
});
|
|
812
|
+
var sizeOf = (value) => measureSize(value).responseBytes;
|
|
813
|
+
var DEFAULT_OUTBOX_BACKOFF = { minDelayMs: 1000, maxDelayMs: 60000, jitter: 0 };
|
|
814
|
+
function createNotificationOutbox(config) {
|
|
815
|
+
const schema = notificationOutboxStateSchema(config.payloadSchema);
|
|
816
|
+
const clock = config.clock ?? (() => new Date);
|
|
817
|
+
const ownerId = config.ownerId ?? crypto.randomUUID();
|
|
818
|
+
const pollIntervalMs = z5.number().int().min(10).parse(config.pollIntervalMs ?? 1000);
|
|
819
|
+
const leaseMs = z5.number().int().min(100).parse(config.leaseMs ?? 30000);
|
|
820
|
+
const maxAttempts = z5.number().int().min(1).max(1e4).parse(config.maxAttempts ?? 100);
|
|
821
|
+
const maxQueue = z5.number().int().min(1).max(1e5).parse(config.maxQueue ?? 1000);
|
|
822
|
+
const maxStateBytes = z5.number().int().min(1024).parse(config.maxStateBytes ?? 1024 * 1024);
|
|
823
|
+
const retainReceipts = z5.number().int().min(0).max(1e5).parse(config.retainReceipts ?? 1000);
|
|
824
|
+
const backoffMs = config.backoffMs ?? ((attempt) => backoffDelay(DEFAULT_OUTBOX_BACKOFF, attempt));
|
|
825
|
+
let timer;
|
|
826
|
+
let running = false;
|
|
827
|
+
let interrupted = false;
|
|
828
|
+
let flushTail = Promise.resolve();
|
|
829
|
+
const bounded = (input) => {
|
|
830
|
+
const parsed = schema.parse(input);
|
|
831
|
+
if (parsed.queue.length > maxQueue) {
|
|
832
|
+
throw new Error(`[stitchkit] notification outbox queue limit (${maxQueue}) exceeded`);
|
|
833
|
+
}
|
|
834
|
+
let receipts = parsed.receipts.slice(0, retainReceipts);
|
|
835
|
+
let next = { ...parsed, receipts };
|
|
836
|
+
while (sizeOf(next) > maxStateBytes && receipts.length > 0) {
|
|
837
|
+
receipts = receipts.slice(0, -1);
|
|
838
|
+
next = { ...parsed, receipts };
|
|
839
|
+
}
|
|
840
|
+
if (sizeOf(next) > maxStateBytes) {
|
|
841
|
+
throw new Error(`[stitchkit] notification outbox state limit (${maxStateBytes} bytes) exceeded`);
|
|
842
|
+
}
|
|
843
|
+
return next;
|
|
844
|
+
};
|
|
845
|
+
const parse = (state) => schema.parse(state ?? emptyOutboxState());
|
|
846
|
+
const enqueue = async (input) => {
|
|
847
|
+
const key = z5.string().min(1).max(512).parse(input.key);
|
|
848
|
+
const payload = config.payloadSchema.parse(input.payload);
|
|
849
|
+
const supersedes = new Set(input.supersedes ?? []);
|
|
850
|
+
return config.store.update((current) => {
|
|
851
|
+
const state = parse(current);
|
|
852
|
+
if (state.queue.some((item) => item.key === key) || state.receipts.some((receipt) => receipt.key === key)) {
|
|
853
|
+
return { state, result: false };
|
|
854
|
+
}
|
|
855
|
+
const now = clock().toISOString();
|
|
856
|
+
const queue = [
|
|
857
|
+
...state.queue.filter((item) => !supersedes.has(item.key)),
|
|
858
|
+
{
|
|
859
|
+
key,
|
|
860
|
+
payload,
|
|
861
|
+
createdAt: now,
|
|
862
|
+
attempts: 0,
|
|
863
|
+
nextAttemptAt: now,
|
|
864
|
+
leaseOwner: null,
|
|
865
|
+
leaseId: null,
|
|
866
|
+
leaseUntil: null
|
|
867
|
+
}
|
|
868
|
+
];
|
|
869
|
+
const next = bounded({ ...state, queue });
|
|
870
|
+
return { state: next, result: true };
|
|
871
|
+
});
|
|
872
|
+
};
|
|
873
|
+
const claimNext = async () => {
|
|
874
|
+
const now = clock();
|
|
875
|
+
return config.store.update((current) => {
|
|
876
|
+
const state = parse(current);
|
|
877
|
+
const candidate = [...state.queue].sort((left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt)).find((item) => Date.parse(item.nextAttemptAt) <= now.getTime() && (item.leaseUntil === null || Date.parse(item.leaseUntil) <= now.getTime()));
|
|
878
|
+
if (!candidate)
|
|
879
|
+
return { state, result: null };
|
|
880
|
+
const leaseId = crypto.randomUUID();
|
|
881
|
+
const claimed = {
|
|
882
|
+
...candidate,
|
|
883
|
+
attempts: candidate.attempts + 1,
|
|
884
|
+
leaseOwner: ownerId,
|
|
885
|
+
leaseId,
|
|
886
|
+
leaseUntil: new Date(now.getTime() + leaseMs).toISOString()
|
|
887
|
+
};
|
|
888
|
+
return {
|
|
889
|
+
state: bounded({
|
|
890
|
+
...state,
|
|
891
|
+
queue: state.queue.map((item) => item.key === candidate.key ? claimed : item)
|
|
892
|
+
}),
|
|
893
|
+
result: claimed
|
|
894
|
+
};
|
|
895
|
+
});
|
|
896
|
+
};
|
|
897
|
+
const acknowledge = async (claimed) => {
|
|
898
|
+
await config.store.update((current) => {
|
|
899
|
+
const state = parse(current);
|
|
900
|
+
const owns = state.queue.some((item) => item.key === claimed.key && item.leaseId === claimed.leaseId);
|
|
901
|
+
if (!owns)
|
|
902
|
+
return { state, result: undefined };
|
|
903
|
+
const receipts = [
|
|
904
|
+
{ key: claimed.key, completedAt: clock().toISOString() },
|
|
905
|
+
...state.receipts.filter((receipt) => receipt.key !== claimed.key)
|
|
906
|
+
].slice(0, retainReceipts);
|
|
907
|
+
return {
|
|
908
|
+
state: bounded({
|
|
909
|
+
...state,
|
|
910
|
+
queue: state.queue.filter((item) => item.key !== claimed.key),
|
|
911
|
+
receipts
|
|
912
|
+
}),
|
|
913
|
+
result: undefined
|
|
914
|
+
};
|
|
915
|
+
});
|
|
916
|
+
};
|
|
917
|
+
const reject = async (claimed, error) => {
|
|
918
|
+
const classification = await config.classify(error);
|
|
919
|
+
return config.store.update((current) => {
|
|
920
|
+
const state = parse(current);
|
|
921
|
+
const live = state.queue.find((item) => item.key === claimed.key && item.leaseId === claimed.leaseId);
|
|
922
|
+
if (!live)
|
|
923
|
+
return { state, result: null };
|
|
924
|
+
const attempts = live.attempts;
|
|
925
|
+
const reason = classification.recipientUnreachable === true ? "recipient-unreachable" : !classification.retryable ? "terminal" : attempts >= maxAttempts ? "attempt-limit" : null;
|
|
926
|
+
if (reason) {
|
|
927
|
+
return {
|
|
928
|
+
state: bounded({
|
|
929
|
+
...state,
|
|
930
|
+
queue: state.queue.filter((item) => item.key !== live.key)
|
|
931
|
+
}),
|
|
932
|
+
result: { item: { ...live, attempts }, error, reason }
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
const rawDelay = backoffMs(attempts);
|
|
936
|
+
const wait = z5.number().finite().nonnegative().max(24 * 60 * 60 * 1000).parse(rawDelay);
|
|
937
|
+
const retry = {
|
|
938
|
+
...live,
|
|
939
|
+
attempts,
|
|
940
|
+
nextAttemptAt: new Date(clock().getTime() + wait).toISOString(),
|
|
941
|
+
leaseOwner: null,
|
|
942
|
+
leaseId: null,
|
|
943
|
+
leaseUntil: null
|
|
944
|
+
};
|
|
945
|
+
return {
|
|
946
|
+
state: bounded({
|
|
947
|
+
...state,
|
|
948
|
+
queue: state.queue.map((item) => item.key === live.key ? retry : item)
|
|
949
|
+
}),
|
|
950
|
+
result: null
|
|
951
|
+
};
|
|
952
|
+
});
|
|
953
|
+
};
|
|
954
|
+
const flushPass = async () => {
|
|
955
|
+
let delivered = 0;
|
|
956
|
+
while (!interrupted) {
|
|
957
|
+
const claimed = await claimNext();
|
|
958
|
+
if (!claimed)
|
|
959
|
+
return delivered;
|
|
960
|
+
try {
|
|
961
|
+
await config.send({
|
|
962
|
+
key: claimed.key,
|
|
963
|
+
payload: claimed.payload,
|
|
964
|
+
attempt: claimed.attempts
|
|
965
|
+
});
|
|
966
|
+
await acknowledge(claimed);
|
|
967
|
+
delivered += 1;
|
|
968
|
+
} catch (error) {
|
|
969
|
+
const dropped = await reject(claimed, error);
|
|
970
|
+
if (dropped)
|
|
971
|
+
await config.onDropped?.(dropped);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return delivered;
|
|
975
|
+
};
|
|
976
|
+
const flush = () => {
|
|
977
|
+
const result = flushTail.then(flushPass, flushPass);
|
|
978
|
+
flushTail = result.then(() => {
|
|
979
|
+
return;
|
|
980
|
+
}, () => {
|
|
981
|
+
return;
|
|
982
|
+
});
|
|
983
|
+
return result;
|
|
984
|
+
};
|
|
985
|
+
const runScheduled = async () => {
|
|
986
|
+
try {
|
|
987
|
+
await flush();
|
|
988
|
+
} catch (error) {
|
|
989
|
+
try {
|
|
990
|
+
await config.onError?.(error);
|
|
991
|
+
} catch {}
|
|
992
|
+
} finally {
|
|
993
|
+
schedule();
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
const schedule = () => {
|
|
997
|
+
if (!running)
|
|
998
|
+
return;
|
|
999
|
+
timer = setTimeout(() => {
|
|
1000
|
+
runScheduled();
|
|
1001
|
+
}, pollIntervalMs);
|
|
1002
|
+
};
|
|
1003
|
+
return {
|
|
1004
|
+
enqueue,
|
|
1005
|
+
flush,
|
|
1006
|
+
start() {
|
|
1007
|
+
if (running)
|
|
1008
|
+
return;
|
|
1009
|
+
running = true;
|
|
1010
|
+
interrupted = false;
|
|
1011
|
+
runScheduled();
|
|
1012
|
+
},
|
|
1013
|
+
async stop() {
|
|
1014
|
+
running = false;
|
|
1015
|
+
interrupted = true;
|
|
1016
|
+
if (timer)
|
|
1017
|
+
clearTimeout(timer);
|
|
1018
|
+
timer = undefined;
|
|
1019
|
+
try {
|
|
1020
|
+
await flushTail;
|
|
1021
|
+
} finally {
|
|
1022
|
+
interrupted = false;
|
|
1023
|
+
}
|
|
1024
|
+
},
|
|
1025
|
+
async state() {
|
|
1026
|
+
return parse(await config.store.read());
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
function notificationOutboxResource(outbox, config = {}) {
|
|
1031
|
+
return defineManagedResource({
|
|
1032
|
+
id: config.id ?? "notification-outbox",
|
|
1033
|
+
start() {
|
|
1034
|
+
outbox.start();
|
|
1035
|
+
return { value: outbox };
|
|
1036
|
+
},
|
|
1037
|
+
async close() {
|
|
1038
|
+
await outbox.stop();
|
|
1039
|
+
},
|
|
1040
|
+
async force() {
|
|
1041
|
+
await outbox.stop();
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
// src/application/process-lifecycle.ts
|
|
1046
|
+
import { z as z6 } from "zod";
|
|
1047
|
+
var LifecycleTerminationSchema = z6.enum([
|
|
1048
|
+
"active",
|
|
1049
|
+
"clean",
|
|
1050
|
+
"forced",
|
|
1051
|
+
"hot-reload",
|
|
1052
|
+
"abnormal"
|
|
1053
|
+
]);
|
|
1054
|
+
var LifecycleRunSchema = z6.object({
|
|
1055
|
+
runId: z6.string().min(1).max(128),
|
|
1056
|
+
pid: z6.number().int().positive(),
|
|
1057
|
+
version: z6.string().min(1).max(256),
|
|
1058
|
+
startedAt: z6.string().datetime({ offset: true }),
|
|
1059
|
+
readyAt: z6.string().datetime({ offset: true }).nullable(),
|
|
1060
|
+
stoppedAt: z6.string().datetime({ offset: true }).nullable(),
|
|
1061
|
+
termination: LifecycleTerminationSchema
|
|
1062
|
+
}).strict();
|
|
1063
|
+
var LifecycleStateSchema = z6.object({
|
|
1064
|
+
schemaVersion: z6.literal(1),
|
|
1065
|
+
runs: z6.array(LifecycleRunSchema)
|
|
1066
|
+
}).strict();
|
|
1067
|
+
var PreviousExitSchema = z6.enum([
|
|
1068
|
+
"first-boot",
|
|
1069
|
+
"hot-reload",
|
|
1070
|
+
"clean",
|
|
1071
|
+
"forced",
|
|
1072
|
+
"handoff",
|
|
1073
|
+
"abnormal"
|
|
1074
|
+
]);
|
|
1075
|
+
var emptyState = () => ({ schemaVersion: 1, runs: [] });
|
|
1076
|
+
var epoch = (value) => Date.parse(value);
|
|
1077
|
+
var elapsed = (later, earlier) => Math.max(0, epoch(later) - epoch(earlier));
|
|
1078
|
+
function normalize(state, retain) {
|
|
1079
|
+
const parsed = LifecycleStateSchema.parse(state ?? emptyState());
|
|
1080
|
+
const runs = [...parsed.runs];
|
|
1081
|
+
for (let index = runs.length - 1;runs.length > retain && index >= 0; index -= 1) {
|
|
1082
|
+
if (runs[index]?.termination !== "active")
|
|
1083
|
+
runs.splice(index, 1);
|
|
1084
|
+
}
|
|
1085
|
+
return { schemaVersion: 1, runs: runs.slice(0, retain) };
|
|
1086
|
+
}
|
|
1087
|
+
var UNKNOWN_VERSION = "unknown";
|
|
1088
|
+
function isVersionChange(previous, next) {
|
|
1089
|
+
return previous !== UNKNOWN_VERSION && next !== UNKNOWN_VERSION && previous !== next;
|
|
1090
|
+
}
|
|
1091
|
+
function transitionProcessStart(source, input) {
|
|
1092
|
+
const retain = z6.number().int().min(1).max(1000).parse(input.retain ?? 20);
|
|
1093
|
+
const state = normalize(source, 1000);
|
|
1094
|
+
const run = LifecycleRunSchema.parse({
|
|
1095
|
+
runId: input.runId,
|
|
1096
|
+
pid: input.pid,
|
|
1097
|
+
version: input.version,
|
|
1098
|
+
startedAt: input.now,
|
|
1099
|
+
readyAt: null,
|
|
1100
|
+
stoppedAt: null,
|
|
1101
|
+
termination: "active"
|
|
1102
|
+
});
|
|
1103
|
+
if (state.runs.some((candidate) => candidate.runId === run.runId)) {
|
|
1104
|
+
throw new Error(`[stitchkit] lifecycle run id already exists: ${run.runId}`);
|
|
1105
|
+
}
|
|
1106
|
+
const previous = state.runs[0] ?? null;
|
|
1107
|
+
let previousExit = "first-boot";
|
|
1108
|
+
let downtimeMs = null;
|
|
1109
|
+
if (previous?.stoppedAt) {
|
|
1110
|
+
previousExit = previous.termination === "forced" || previous.termination === "abnormal" || previous.termination === "hot-reload" ? previous.termination : "clean";
|
|
1111
|
+
downtimeMs = elapsed(run.startedAt, previous.stoppedAt);
|
|
1112
|
+
} else if (previous) {
|
|
1113
|
+
if (previous.pid === run.pid)
|
|
1114
|
+
previousExit = "hot-reload";
|
|
1115
|
+
else if (isVersionChange(previous.version, run.version))
|
|
1116
|
+
previousExit = "handoff";
|
|
1117
|
+
else
|
|
1118
|
+
previousExit = input.sameVersionOverlap ?? "abnormal";
|
|
1119
|
+
}
|
|
1120
|
+
const runs = state.runs.map((candidate) => {
|
|
1121
|
+
if (candidate.runId !== previous?.runId || candidate.termination !== "active")
|
|
1122
|
+
return candidate;
|
|
1123
|
+
if (previousExit === "hot-reload") {
|
|
1124
|
+
return { ...candidate, stoppedAt: run.startedAt, termination: "hot-reload" };
|
|
1125
|
+
}
|
|
1126
|
+
if (previousExit === "abnormal") {
|
|
1127
|
+
return { ...candidate, stoppedAt: run.startedAt, termination: "abnormal" };
|
|
1128
|
+
}
|
|
1129
|
+
return candidate;
|
|
1130
|
+
});
|
|
1131
|
+
const next = normalize({ schemaVersion: 1, runs: [run, ...runs] }, retain);
|
|
1132
|
+
return {
|
|
1133
|
+
state: next,
|
|
1134
|
+
fact: {
|
|
1135
|
+
type: "started",
|
|
1136
|
+
runId: run.runId,
|
|
1137
|
+
pid: run.pid,
|
|
1138
|
+
version: run.version,
|
|
1139
|
+
startedAt: run.startedAt,
|
|
1140
|
+
previousExit,
|
|
1141
|
+
previousRunId: previous?.runId ?? null,
|
|
1142
|
+
previousPid: previous?.pid ?? null,
|
|
1143
|
+
previousVersion: previous?.version ?? null,
|
|
1144
|
+
versionChanged: previous !== null && isVersionChange(previous.version, run.version),
|
|
1145
|
+
downtimeMs
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
function transitionProcessReady(source, input) {
|
|
1150
|
+
const retain = input.retain ?? 20;
|
|
1151
|
+
const state = normalize(source, retain);
|
|
1152
|
+
const target = state.runs.find((run) => run.runId === input.runId && run.pid === input.pid && run.termination === "active");
|
|
1153
|
+
if (!target) {
|
|
1154
|
+
return {
|
|
1155
|
+
state,
|
|
1156
|
+
fact: {
|
|
1157
|
+
type: "ready",
|
|
1158
|
+
runId: input.runId,
|
|
1159
|
+
pid: input.pid,
|
|
1160
|
+
readyAt: input.now,
|
|
1161
|
+
startupMs: 0,
|
|
1162
|
+
recorded: false
|
|
1163
|
+
}
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
const readyAt = target.readyAt ?? input.now;
|
|
1167
|
+
return {
|
|
1168
|
+
state: {
|
|
1169
|
+
schemaVersion: 1,
|
|
1170
|
+
runs: state.runs.map((run) => run.runId === target.runId && run.readyAt === null ? { ...run, readyAt } : run)
|
|
1171
|
+
},
|
|
1172
|
+
fact: {
|
|
1173
|
+
type: "ready",
|
|
1174
|
+
runId: target.runId,
|
|
1175
|
+
pid: target.pid,
|
|
1176
|
+
readyAt,
|
|
1177
|
+
startupMs: elapsed(readyAt, target.startedAt),
|
|
1178
|
+
recorded: target.readyAt === null
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
function transitionProcessShutdown(source, input) {
|
|
1183
|
+
const state = normalize(source, input.retain ?? 20);
|
|
1184
|
+
const target = state.runs.find((run) => run.runId === input.runId && run.pid === input.pid && run.termination === "active");
|
|
1185
|
+
const termination = input.forced ? "forced" : "clean";
|
|
1186
|
+
if (!target) {
|
|
1187
|
+
return {
|
|
1188
|
+
state,
|
|
1189
|
+
fact: {
|
|
1190
|
+
type: "stopped",
|
|
1191
|
+
runId: input.runId,
|
|
1192
|
+
pid: input.pid,
|
|
1193
|
+
stoppedAt: input.now,
|
|
1194
|
+
uptimeMs: null,
|
|
1195
|
+
termination,
|
|
1196
|
+
recorded: false
|
|
1197
|
+
}
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
state: {
|
|
1202
|
+
schemaVersion: 1,
|
|
1203
|
+
runs: state.runs.map((run) => run.runId === target.runId ? { ...run, stoppedAt: input.now, termination } : run)
|
|
1204
|
+
},
|
|
1205
|
+
fact: {
|
|
1206
|
+
type: "stopped",
|
|
1207
|
+
runId: target.runId,
|
|
1208
|
+
pid: target.pid,
|
|
1209
|
+
stoppedAt: input.now,
|
|
1210
|
+
uptimeMs: elapsed(input.now, target.startedAt),
|
|
1211
|
+
termination,
|
|
1212
|
+
recorded: true
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
function createProcessLifecycleLedger(config) {
|
|
1217
|
+
const clock = config.clock ?? (() => new Date);
|
|
1218
|
+
const pid = z6.number().int().positive().parse(config.pid ?? process.pid);
|
|
1219
|
+
const retain = z6.number().int().min(1).max(1000).parse(config.retain ?? 20);
|
|
1220
|
+
const configuredRunId = config.runId;
|
|
1221
|
+
const nextRunId = typeof configuredRunId === "function" ? configuredRunId : configuredRunId === undefined ? () => crypto.randomUUID() : () => configuredRunId;
|
|
1222
|
+
let runId = nextRunId();
|
|
1223
|
+
let started = false;
|
|
1224
|
+
const listeners = new Set;
|
|
1225
|
+
const publish = (fact) => {
|
|
1226
|
+
for (const listener of listeners) {
|
|
1227
|
+
Promise.resolve().then(() => listener(fact)).catch((error) => config.onSubscriberError?.(error, fact));
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
return {
|
|
1231
|
+
async recordStart({ version }) {
|
|
1232
|
+
if (started)
|
|
1233
|
+
runId = nextRunId();
|
|
1234
|
+
const fact = await config.store.update((state) => {
|
|
1235
|
+
const transition = transitionProcessStart(state, {
|
|
1236
|
+
runId,
|
|
1237
|
+
pid,
|
|
1238
|
+
version,
|
|
1239
|
+
now: clock().toISOString(),
|
|
1240
|
+
retain,
|
|
1241
|
+
sameVersionOverlap: config.sameVersionOverlap
|
|
1242
|
+
});
|
|
1243
|
+
return { state: transition.state, result: transition.fact };
|
|
1244
|
+
});
|
|
1245
|
+
started = true;
|
|
1246
|
+
publish(fact);
|
|
1247
|
+
return fact;
|
|
1248
|
+
},
|
|
1249
|
+
async recordReady() {
|
|
1250
|
+
const fact = await config.store.update((state) => {
|
|
1251
|
+
const transition = transitionProcessReady(state, {
|
|
1252
|
+
runId,
|
|
1253
|
+
pid,
|
|
1254
|
+
now: clock().toISOString(),
|
|
1255
|
+
retain
|
|
1256
|
+
});
|
|
1257
|
+
return { state: transition.state, result: transition.fact };
|
|
1258
|
+
});
|
|
1259
|
+
if (fact.recorded)
|
|
1260
|
+
publish(fact);
|
|
1261
|
+
return fact;
|
|
1262
|
+
},
|
|
1263
|
+
async recordShutdown(input) {
|
|
1264
|
+
const fact = await config.store.update((state) => {
|
|
1265
|
+
const transition = transitionProcessShutdown(state, {
|
|
1266
|
+
runId,
|
|
1267
|
+
pid,
|
|
1268
|
+
now: clock().toISOString(),
|
|
1269
|
+
forced: input?.forced,
|
|
1270
|
+
retain
|
|
1271
|
+
});
|
|
1272
|
+
return { state: transition.state, result: transition.fact };
|
|
1273
|
+
});
|
|
1274
|
+
if (fact.recorded)
|
|
1275
|
+
publish(fact);
|
|
1276
|
+
return fact;
|
|
1277
|
+
},
|
|
1278
|
+
async current() {
|
|
1279
|
+
const state = normalize(await config.store.read(), retain);
|
|
1280
|
+
return state.runs.find((run) => run.runId === runId && run.pid === pid) ?? null;
|
|
1281
|
+
},
|
|
1282
|
+
async runs() {
|
|
1283
|
+
return normalize(await config.store.read(), retain).runs;
|
|
1284
|
+
},
|
|
1285
|
+
subscribe(listener) {
|
|
1286
|
+
listeners.add(listener);
|
|
1287
|
+
return () => listeners.delete(listener);
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
function lifecycleLedgerResource(ledger, config) {
|
|
1292
|
+
let stopped = false;
|
|
1293
|
+
let shutdown;
|
|
1294
|
+
const stop = async (forced) => {
|
|
1295
|
+
if (stopped)
|
|
1296
|
+
return;
|
|
1297
|
+
if (!shutdown)
|
|
1298
|
+
shutdown = ledger.recordShutdown({ forced });
|
|
1299
|
+
try {
|
|
1300
|
+
await shutdown;
|
|
1301
|
+
stopped = true;
|
|
1302
|
+
} finally {
|
|
1303
|
+
if (!stopped)
|
|
1304
|
+
shutdown = undefined;
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
return defineManagedResource({
|
|
1308
|
+
id: config.id ?? "lifecycle",
|
|
1309
|
+
async start() {
|
|
1310
|
+
stopped = false;
|
|
1311
|
+
shutdown = undefined;
|
|
1312
|
+
await ledger.recordStart({ version: config.version });
|
|
1313
|
+
return { value: ledger };
|
|
1314
|
+
},
|
|
1315
|
+
async activate() {
|
|
1316
|
+
await ledger.recordReady();
|
|
1317
|
+
},
|
|
1318
|
+
async close() {
|
|
1319
|
+
await stop(false);
|
|
1320
|
+
},
|
|
1321
|
+
async force() {
|
|
1322
|
+
await stop(true);
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
// src/application/revision-signal.ts
|
|
1327
|
+
import { z as z7 } from "zod";
|
|
1328
|
+
var NonNegativeSafeIntegerSchema = z7.number().int().nonnegative().safe();
|
|
1329
|
+
var PositiveSafeIntegerSchema2 = z7.number().int().positive().safe();
|
|
1330
|
+
var TimerDelaySchema = z7.number().int().positive().max(2147483647);
|
|
1331
|
+
var RevisionSignalStateSchema = z7.enum(["open", "closed"]);
|
|
1332
|
+
var RevisionSignalWaitOutcomeSchema = z7.enum([
|
|
1333
|
+
"changed",
|
|
1334
|
+
"timed-out",
|
|
1335
|
+
"aborted",
|
|
1336
|
+
"closed",
|
|
1337
|
+
"capacity"
|
|
1338
|
+
]);
|
|
1339
|
+
var RevisionSignalWaitResultSchema = z7.object({
|
|
1340
|
+
outcome: RevisionSignalWaitOutcomeSchema,
|
|
1341
|
+
revision: NonNegativeSafeIntegerSchema
|
|
1342
|
+
}).strict().readonly();
|
|
1343
|
+
var RevisionSignalAdvanceResultSchema = z7.object({
|
|
1344
|
+
outcome: z7.enum(["advanced", "closed"]),
|
|
1345
|
+
revision: NonNegativeSafeIntegerSchema
|
|
1346
|
+
}).strict().readonly();
|
|
1347
|
+
var RevisionSignalSnapshotSchema = z7.object({
|
|
1348
|
+
state: RevisionSignalStateSchema,
|
|
1349
|
+
revision: NonNegativeSafeIntegerSchema,
|
|
1350
|
+
pending: NonNegativeSafeIntegerSchema,
|
|
1351
|
+
maxWaiters: PositiveSafeIntegerSchema2,
|
|
1352
|
+
advances: NonNegativeSafeIntegerSchema,
|
|
1353
|
+
refusedAdvances: NonNegativeSafeIntegerSchema,
|
|
1354
|
+
waits: NonNegativeSafeIntegerSchema,
|
|
1355
|
+
changed: NonNegativeSafeIntegerSchema,
|
|
1356
|
+
timedOut: NonNegativeSafeIntegerSchema,
|
|
1357
|
+
aborted: NonNegativeSafeIntegerSchema,
|
|
1358
|
+
closedWaits: NonNegativeSafeIntegerSchema,
|
|
1359
|
+
capacityRefusals: NonNegativeSafeIntegerSchema,
|
|
1360
|
+
clockFailures: NonNegativeSafeIntegerSchema
|
|
1361
|
+
}).strict().readonly();
|
|
1362
|
+
var systemClock = {
|
|
1363
|
+
schedule(callback, delayMs) {
|
|
1364
|
+
const timer = setTimeout(callback, delayMs);
|
|
1365
|
+
return { cancel: () => clearTimeout(timer) };
|
|
1366
|
+
}
|
|
1367
|
+
};
|
|
1368
|
+
function createRevisionSignal(config) {
|
|
1369
|
+
const maxWaiters = PositiveSafeIntegerSchema2.parse(config.maxWaiters);
|
|
1370
|
+
const clock = config.clock ?? systemClock;
|
|
1371
|
+
const waiters = new Set;
|
|
1372
|
+
let state = "open";
|
|
1373
|
+
let revision = 0;
|
|
1374
|
+
let advances = 0;
|
|
1375
|
+
let refusedAdvances = 0;
|
|
1376
|
+
let waits = 0;
|
|
1377
|
+
let changed = 0;
|
|
1378
|
+
let timedOut = 0;
|
|
1379
|
+
let aborted = 0;
|
|
1380
|
+
let closedWaits = 0;
|
|
1381
|
+
let capacityRefusals = 0;
|
|
1382
|
+
let clockFailures = 0;
|
|
1383
|
+
const result = (outcome) => {
|
|
1384
|
+
if (outcome === "changed")
|
|
1385
|
+
changed += 1;
|
|
1386
|
+
else if (outcome === "timed-out")
|
|
1387
|
+
timedOut += 1;
|
|
1388
|
+
else if (outcome === "aborted")
|
|
1389
|
+
aborted += 1;
|
|
1390
|
+
else if (outcome === "closed")
|
|
1391
|
+
closedWaits += 1;
|
|
1392
|
+
else
|
|
1393
|
+
capacityRefusals += 1;
|
|
1394
|
+
return RevisionSignalWaitResultSchema.parse({ outcome, revision });
|
|
1395
|
+
};
|
|
1396
|
+
const snapshot = () => RevisionSignalSnapshotSchema.parse({
|
|
1397
|
+
state,
|
|
1398
|
+
revision,
|
|
1399
|
+
pending: waiters.size,
|
|
1400
|
+
maxWaiters,
|
|
1401
|
+
advances,
|
|
1402
|
+
refusedAdvances,
|
|
1403
|
+
waits,
|
|
1404
|
+
changed,
|
|
1405
|
+
timedOut,
|
|
1406
|
+
aborted,
|
|
1407
|
+
closedWaits,
|
|
1408
|
+
capacityRefusals,
|
|
1409
|
+
clockFailures
|
|
1410
|
+
});
|
|
1411
|
+
return {
|
|
1412
|
+
advance() {
|
|
1413
|
+
if (state === "closed") {
|
|
1414
|
+
refusedAdvances += 1;
|
|
1415
|
+
return RevisionSignalAdvanceResultSchema.parse({ outcome: "closed", revision });
|
|
1416
|
+
}
|
|
1417
|
+
if (revision === Number.MAX_SAFE_INTEGER) {
|
|
1418
|
+
throw new RangeError("Revision signal exhausted the safe-integer revision range");
|
|
1419
|
+
}
|
|
1420
|
+
revision += 1;
|
|
1421
|
+
advances += 1;
|
|
1422
|
+
for (const waiter of [...waiters])
|
|
1423
|
+
waiter.settle("changed");
|
|
1424
|
+
return RevisionSignalAdvanceResultSchema.parse({ outcome: "advanced", revision });
|
|
1425
|
+
},
|
|
1426
|
+
wait(after, options = {}) {
|
|
1427
|
+
const parsedAfter = NonNegativeSafeIntegerSchema.parse(after);
|
|
1428
|
+
const timeoutMs = options.timeoutMs === undefined ? undefined : TimerDelaySchema.parse(options.timeoutMs);
|
|
1429
|
+
if (parsedAfter > revision) {
|
|
1430
|
+
throw new RangeError(`Revision signal cannot wait after future revision ${parsedAfter}; current revision is ${revision}`);
|
|
1431
|
+
}
|
|
1432
|
+
waits += 1;
|
|
1433
|
+
if (state === "closed")
|
|
1434
|
+
return Promise.resolve(result("closed"));
|
|
1435
|
+
if (parsedAfter < revision)
|
|
1436
|
+
return Promise.resolve(result("changed"));
|
|
1437
|
+
if (options.signal?.aborted)
|
|
1438
|
+
return Promise.resolve(result("aborted"));
|
|
1439
|
+
if (waiters.size >= maxWaiters)
|
|
1440
|
+
return Promise.resolve(result("capacity"));
|
|
1441
|
+
return new Promise((resolve) => {
|
|
1442
|
+
let settled = false;
|
|
1443
|
+
let timer;
|
|
1444
|
+
const waiter = {
|
|
1445
|
+
settle(outcome) {
|
|
1446
|
+
if (settled)
|
|
1447
|
+
return;
|
|
1448
|
+
settled = true;
|
|
1449
|
+
timer?.cancel();
|
|
1450
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
1451
|
+
waiters.delete(waiter);
|
|
1452
|
+
resolve(result(outcome));
|
|
1453
|
+
}
|
|
1454
|
+
};
|
|
1455
|
+
function onAbort() {
|
|
1456
|
+
waiter.settle("aborted");
|
|
1457
|
+
}
|
|
1458
|
+
waiters.add(waiter);
|
|
1459
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
1460
|
+
if (timeoutMs !== undefined) {
|
|
1461
|
+
try {
|
|
1462
|
+
const scheduled = clock.schedule(() => waiter.settle("timed-out"), timeoutMs);
|
|
1463
|
+
timer = scheduled;
|
|
1464
|
+
if (settled)
|
|
1465
|
+
scheduled.cancel();
|
|
1466
|
+
} catch (error) {
|
|
1467
|
+
settled = true;
|
|
1468
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
1469
|
+
waiters.delete(waiter);
|
|
1470
|
+
clockFailures += 1;
|
|
1471
|
+
throw error;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
},
|
|
1476
|
+
close() {
|
|
1477
|
+
if (state === "closed")
|
|
1478
|
+
return snapshot();
|
|
1479
|
+
state = "closed";
|
|
1480
|
+
for (const waiter of [...waiters])
|
|
1481
|
+
waiter.settle("closed");
|
|
1482
|
+
return snapshot();
|
|
1483
|
+
},
|
|
1484
|
+
getSnapshot: snapshot
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
781
1487
|
// src/application/server-resource.ts
|
|
782
1488
|
function managedServerResource(config) {
|
|
783
1489
|
let shutdownPromise;
|
|
@@ -1081,17 +1787,26 @@ function readErrorCode(error) {
|
|
|
1081
1787
|
}
|
|
1082
1788
|
export {
|
|
1083
1789
|
watchKey,
|
|
1790
|
+
transitionProcessStart,
|
|
1791
|
+
transitionProcessShutdown,
|
|
1792
|
+
transitionProcessReady,
|
|
1084
1793
|
sqliteKeyspaceBackend,
|
|
1085
1794
|
readDiagnosticJournalLockDiagnosis,
|
|
1086
1795
|
projectApplicationStatus,
|
|
1087
1796
|
openKeyspace,
|
|
1797
|
+
notificationOutboxStateSchema,
|
|
1798
|
+
notificationOutboxResource,
|
|
1088
1799
|
memoryKeyspaceBackend,
|
|
1089
1800
|
managedServerResource,
|
|
1090
1801
|
managedResourceDependencyId,
|
|
1802
|
+
lifecycleLedgerResource,
|
|
1091
1803
|
keyspaceResource,
|
|
1092
1804
|
defineManagedResource,
|
|
1093
1805
|
defineKeyspace,
|
|
1094
1806
|
createWatchHub,
|
|
1807
|
+
createRevisionSignal,
|
|
1808
|
+
createProcessLifecycleLedger,
|
|
1809
|
+
createNotificationOutbox,
|
|
1095
1810
|
createManagedSchedule,
|
|
1096
1811
|
createDecisionPipeline,
|
|
1097
1812
|
createCreditWindow,
|
|
@@ -1104,6 +1819,12 @@ export {
|
|
|
1104
1819
|
createApplication,
|
|
1105
1820
|
createActivityProjection,
|
|
1106
1821
|
applicationLifecycleEvent,
|
|
1822
|
+
RevisionSignalWaitResultSchema,
|
|
1823
|
+
RevisionSignalWaitOutcomeSchema,
|
|
1824
|
+
RevisionSignalStateSchema,
|
|
1825
|
+
RevisionSignalSnapshotSchema,
|
|
1826
|
+
RevisionSignalAdvanceResultSchema,
|
|
1827
|
+
PreviousExitSchema,
|
|
1107
1828
|
PolicyDecisionSchema,
|
|
1108
1829
|
ManagedScheduleStatusSchema,
|
|
1109
1830
|
ManagedScheduleOverlapSchema,
|
|
@@ -1111,6 +1832,9 @@ export {
|
|
|
1111
1832
|
ManagedScheduleDescriptorSchema,
|
|
1112
1833
|
ManagedResourceStateSchema,
|
|
1113
1834
|
ManagedResourceSnapshotSchema,
|
|
1835
|
+
LifecycleTerminationSchema,
|
|
1836
|
+
LifecycleStateSchema,
|
|
1837
|
+
LifecycleRunSchema,
|
|
1114
1838
|
DiagnosticJournalWaitResultSchema,
|
|
1115
1839
|
DiagnosticJournalSubmitResultSchema,
|
|
1116
1840
|
DiagnosticJournalStatusSchema,
|