stitchkit 0.94.1 → 0.95.1
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 +57 -0
- package/dist/agent-runtime/provider-origin.d.ts +7 -0
- package/dist/agent-runtime/provider-origin.d.ts.map +1 -1
- package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
- package/dist/application/directory-inbox-contract.d.ts +129 -0
- package/dist/application/directory-inbox-contract.d.ts.map +1 -0
- package/dist/application/directory-inbox.d.ts +3 -0
- package/dist/application/directory-inbox.d.ts.map +1 -0
- package/dist/application/process-lifecycle-transitions.d.ts +175 -0
- package/dist/application/process-lifecycle-transitions.d.ts.map +1 -0
- package/dist/application/process-lifecycle.d.ts +3 -131
- package/dist/application/process-lifecycle.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/harness.js +1 -1
- package/dist/entrypoints/agent-runtime.js +1 -1
- package/dist/entrypoints/application/directory-inbox.d.ts +11 -0
- package/dist/entrypoints/application/directory-inbox.d.ts.map +1 -0
- package/dist/entrypoints/application/directory-inbox.js +221 -0
- package/dist/entrypoints/application.d.ts +3 -1
- package/dist/entrypoints/application.d.ts.map +1 -1
- package/dist/entrypoints/application.js +151 -56
- package/dist/entrypoints/server.js +6 -219
- package/dist/index-5jrd0yng.js +114 -0
- package/dist/{index-7f68ghdn.js → index-8zja4pkf.js} +23 -1
- package/dist/index-tm88avnj.js +221 -0
- package/llms/application-directory-inbox.txt +9 -0
- package/llms/application.2.txt +7 -5
- package/llms/application.txt +88 -24
- package/llms/stitchkit.txt +4 -3
- package/llms/{upgrading-0.37.0-0.50.0.txt → upgrading-0.37.0-0.53.0.txt} +25 -3
- package/llms/{upgrading-0.53.0-0.67.0.txt → upgrading-0.55.0-0.68.0.txt} +53 -25
- package/llms/{upgrading-0.68.0-0.94.0.txt → upgrading-0.69.0-0.95.0.txt} +45 -53
- package/llms/upgrading.txt +3 -3
- package/llms-full.txt +141 -32
- package/llms.txt +6 -5
- package/package.json +5 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DirectoryInboxStateSchema,
|
|
3
|
+
claimEntry,
|
|
4
|
+
completeEntry,
|
|
5
|
+
emptyDirectoryInboxState,
|
|
6
|
+
forgetMissing,
|
|
7
|
+
releaseEntry,
|
|
8
|
+
withRejection
|
|
9
|
+
} from "../../index-5jrd0yng.js";
|
|
10
|
+
import {
|
|
11
|
+
defineManagedResource
|
|
12
|
+
} from "../../index-2k4yrqkc.js";
|
|
13
|
+
import {
|
|
14
|
+
createFileStateStore
|
|
15
|
+
} from "../../index-tm88avnj.js";
|
|
16
|
+
import {
|
|
17
|
+
backoffDelay
|
|
18
|
+
} from "../../index-ngfhvfpd.js";
|
|
19
|
+
import"../../index-hffjpmq9.js";
|
|
20
|
+
|
|
21
|
+
// src/application/directory-inbox.ts
|
|
22
|
+
import { mkdir, readdir, readFile, rename, stat, unlink } from "node:fs/promises";
|
|
23
|
+
import { join } from "node:path";
|
|
24
|
+
import { z } from "zod";
|
|
25
|
+
var REJECTED = "rejected";
|
|
26
|
+
var ENTRY_NAME = /^[^.].*\.json$/;
|
|
27
|
+
var RETRY_BACKOFF = { minDelayMs: 1000, maxDelayMs: 300000, jitter: 0 };
|
|
28
|
+
var absent = (error) => error instanceof Error && ("code" in error) && error.code === "ENOENT";
|
|
29
|
+
async function quietly(run) {
|
|
30
|
+
try {
|
|
31
|
+
await run();
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (!absent(error))
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function resolveLimits(config) {
|
|
38
|
+
const integer = z.number().int();
|
|
39
|
+
return {
|
|
40
|
+
pollIntervalMs: integer.min(10).parse(config.pollIntervalMs ?? 1000),
|
|
41
|
+
leaseMs: integer.min(100).parse(config.leaseMs ?? 300000),
|
|
42
|
+
maxAttempts: integer.min(1).max(1e4).parse(config.maxAttempts ?? 20),
|
|
43
|
+
maxEntryBytes: integer.min(1).parse(config.maxEntryBytes ?? 1024 * 1024),
|
|
44
|
+
retain: integer.min(1).max(1e5).parse(config.retain ?? 1000)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function entryNames(directory) {
|
|
48
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
49
|
+
return entries.filter((entry) => entry.isFile() && ENTRY_NAME.test(entry.name)).map((entry) => entry.name).sort();
|
|
50
|
+
}
|
|
51
|
+
async function readEntry(path, schema, maxEntryBytes) {
|
|
52
|
+
try {
|
|
53
|
+
const { size } = await stat(path);
|
|
54
|
+
if (size > maxEntryBytes) {
|
|
55
|
+
return { reason: "too-large", detail: `${size} bytes over the ${maxEntryBytes} limit` };
|
|
56
|
+
}
|
|
57
|
+
const text = await readFile(path, "utf8");
|
|
58
|
+
let json;
|
|
59
|
+
try {
|
|
60
|
+
json = JSON.parse(text);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
return { reason: "invalid", detail: String(error).slice(0, 1000) };
|
|
63
|
+
}
|
|
64
|
+
const parsed = schema.safeParse(json);
|
|
65
|
+
return parsed.success ? { entry: parsed.data } : { reason: "invalid", detail: z.prettifyError(parsed.error).slice(0, 1000) };
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (absent(error))
|
|
68
|
+
return null;
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function createDirectoryInbox(config) {
|
|
73
|
+
const limits = resolveLimits(config);
|
|
74
|
+
const clock = config.clock ?? (() => new Date);
|
|
75
|
+
const store = config.store ?? createFileStateStore(join(config.directory, ".inbox-state.json"), {
|
|
76
|
+
schema: DirectoryInboxStateSchema
|
|
77
|
+
});
|
|
78
|
+
const parse = (state) => DirectoryInboxStateSchema.parse(state ?? emptyDirectoryInboxState());
|
|
79
|
+
const update = (transition) => store.update((current) => transition(parse(current)));
|
|
80
|
+
let running = false;
|
|
81
|
+
let admitting = false;
|
|
82
|
+
let timer;
|
|
83
|
+
let forced = new AbortController;
|
|
84
|
+
let tail = Promise.resolve();
|
|
85
|
+
const report = async (error) => {
|
|
86
|
+
try {
|
|
87
|
+
await config.onError?.(error);
|
|
88
|
+
} catch {}
|
|
89
|
+
};
|
|
90
|
+
const setAside = async (key, rejection) => {
|
|
91
|
+
await mkdir(join(config.directory, REJECTED), { recursive: true });
|
|
92
|
+
await quietly(() => rename(join(config.directory, key), join(config.directory, REJECTED, key)));
|
|
93
|
+
if (rejection)
|
|
94
|
+
await config.onRejected?.(rejection);
|
|
95
|
+
};
|
|
96
|
+
const reject = async (key, reason, detail) => {
|
|
97
|
+
const rejection = { key, reason, detail, rejectedAt: clock().toISOString() };
|
|
98
|
+
await update((state) => ({
|
|
99
|
+
state: withRejection(state, rejection, limits.retain),
|
|
100
|
+
result: undefined
|
|
101
|
+
}));
|
|
102
|
+
await setAside(key, rejection);
|
|
103
|
+
};
|
|
104
|
+
const deliver = async (claim) => {
|
|
105
|
+
const path = join(config.directory, claim.key);
|
|
106
|
+
const read = await readEntry(path, config.schema, limits.maxEntryBytes);
|
|
107
|
+
if (read === null)
|
|
108
|
+
return false;
|
|
109
|
+
if ("reason" in read) {
|
|
110
|
+
await reject(claim.key, read.reason, read.detail);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
await config.handle({
|
|
115
|
+
key: claim.key,
|
|
116
|
+
entry: read.entry,
|
|
117
|
+
attempt: claim.attempts,
|
|
118
|
+
signal: forced.signal
|
|
119
|
+
});
|
|
120
|
+
} catch (error) {
|
|
121
|
+
await report(error);
|
|
122
|
+
const retryAt = new Date(clock().getTime() + backoffDelay(RETRY_BACKOFF, claim.attempts));
|
|
123
|
+
await update((state) => ({
|
|
124
|
+
state: releaseEntry(state, claim, retryAt),
|
|
125
|
+
result: undefined
|
|
126
|
+
}));
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
await update((state) => ({
|
|
130
|
+
state: completeEntry(state, claim.key, clock(), limits.retain),
|
|
131
|
+
result: undefined
|
|
132
|
+
}));
|
|
133
|
+
await quietly(() => unlink(path));
|
|
134
|
+
return true;
|
|
135
|
+
};
|
|
136
|
+
const pass = async () => {
|
|
137
|
+
const names = await entryNames(config.directory);
|
|
138
|
+
await update((state) => ({
|
|
139
|
+
state: forgetMissing(state, new Set(names), clock()),
|
|
140
|
+
result: undefined
|
|
141
|
+
}));
|
|
142
|
+
let handled = 0;
|
|
143
|
+
for (const key of names) {
|
|
144
|
+
if (!admitting && running)
|
|
145
|
+
break;
|
|
146
|
+
const { step } = await update((state) => {
|
|
147
|
+
const next = claimEntry(state, { key, now: clock(), ...limits });
|
|
148
|
+
return { state: next.state, result: next };
|
|
149
|
+
});
|
|
150
|
+
if (step.kind === "remove")
|
|
151
|
+
await quietly(() => unlink(join(config.directory, key)));
|
|
152
|
+
else if (step.kind === "set-aside")
|
|
153
|
+
await setAside(key);
|
|
154
|
+
else if (step.kind === "reject")
|
|
155
|
+
await setAside(key, step.rejection);
|
|
156
|
+
else if (step.kind === "deliver" && await deliver(step.claim))
|
|
157
|
+
handled += 1;
|
|
158
|
+
}
|
|
159
|
+
return handled;
|
|
160
|
+
};
|
|
161
|
+
const flush = () => {
|
|
162
|
+
const result = tail.then(pass, pass);
|
|
163
|
+
tail = result.catch(() => {
|
|
164
|
+
return;
|
|
165
|
+
});
|
|
166
|
+
return result;
|
|
167
|
+
};
|
|
168
|
+
const poll = async () => {
|
|
169
|
+
try {
|
|
170
|
+
await flush();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
await report(error);
|
|
173
|
+
}
|
|
174
|
+
if (admitting)
|
|
175
|
+
timer = setTimeout(() => void poll(), limits.pollIntervalMs);
|
|
176
|
+
};
|
|
177
|
+
const stopAdmitting = () => {
|
|
178
|
+
admitting = false;
|
|
179
|
+
if (timer)
|
|
180
|
+
clearTimeout(timer);
|
|
181
|
+
timer = undefined;
|
|
182
|
+
};
|
|
183
|
+
const inbox = {
|
|
184
|
+
flush,
|
|
185
|
+
async state() {
|
|
186
|
+
return parse(await store.read());
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
return defineManagedResource({
|
|
190
|
+
id: config.id,
|
|
191
|
+
...config.dependsOn && { dependsOn: config.dependsOn },
|
|
192
|
+
async start() {
|
|
193
|
+
await mkdir(config.directory, { recursive: true });
|
|
194
|
+
forced = new AbortController;
|
|
195
|
+
return { value: inbox };
|
|
196
|
+
},
|
|
197
|
+
activate() {
|
|
198
|
+
running = true;
|
|
199
|
+
admitting = true;
|
|
200
|
+
poll();
|
|
201
|
+
},
|
|
202
|
+
stopAdmission() {
|
|
203
|
+
stopAdmitting();
|
|
204
|
+
},
|
|
205
|
+
async drain() {
|
|
206
|
+
await tail;
|
|
207
|
+
},
|
|
208
|
+
async close() {
|
|
209
|
+
stopAdmitting();
|
|
210
|
+
await tail;
|
|
211
|
+
},
|
|
212
|
+
async force() {
|
|
213
|
+
stopAdmitting();
|
|
214
|
+
forced.abort();
|
|
215
|
+
await tail;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
export {
|
|
220
|
+
createDirectoryInbox
|
|
221
|
+
};
|
|
@@ -2,6 +2,7 @@ export { type ActivityId, ActivityIdSchema, type ActivityLiveState, ActivityLive
|
|
|
2
2
|
export { type BoundedAdmission, type BoundedAdmissionClock, type BoundedAdmissionConfig, type BoundedAdmissionDrainOptions, type BoundedAdmissionDrainResult, type BoundedAdmissionForceResult, type BoundedAdmissionLeaseResult, type BoundedAdmissionPerKeyLimitResolver, type BoundedAdmissionPerKeyLimits, BoundedAdmissionPerKeyLimitsSchema, type BoundedAdmissionPolicy, BoundedAdmissionPolicySchema, BoundedAdmissionRefusalError, type BoundedAdmissionRefusalReason, BoundedAdmissionRefusalReasonSchema, type BoundedAdmissionRefusedResult, type BoundedAdmissionResult, type BoundedAdmissionSnapshot, BoundedAdmissionSnapshotSchema, type BoundedAdmissionState, BoundedAdmissionStateSchema, type BoundedOperationLease, type BoundedOperationRunContext, type BoundedOperationRunOptions, BoundedOperationWaitError, type BoundedRateBudget, BoundedRateBudgetSchema, createBoundedAdmission, } from '../application/admission.js';
|
|
3
3
|
export { createDecisionPipeline, type DecisionPipeline, type DecisionPipelineConfig, type DecisionPolicy, DecisionPolicyError, type DecisionResult, type DecisionTraceEntry, DecisionUndecidedError, type PolicyDecision, PolicyDecisionSchema, } from '../application/decisions.js';
|
|
4
4
|
export { type DiagnosticJournal, type DiagnosticJournalCloseResult, DiagnosticJournalCloseResultSchema, type DiagnosticJournalConfig, type DiagnosticJournalFailure, type DiagnosticJournalFailurePhase, DiagnosticJournalFailurePhaseSchema, type DiagnosticJournalFrame, DiagnosticJournalFrameSchema, type DiagnosticJournalLimits, DiagnosticJournalLimitsSchema, type DiagnosticJournalLockDiagnosis, type DiagnosticJournalLockPolicy, DiagnosticJournalLockPolicySchema, type DiagnosticJournalRefusalReason, DiagnosticJournalRefusalReasonSchema, type DiagnosticJournalState, DiagnosticJournalStateSchema, type DiagnosticJournalStatus, DiagnosticJournalStatusSchema, type DiagnosticJournalSubmitResult, DiagnosticJournalSubmitResultSchema, type DiagnosticJournalWaitOptions, type DiagnosticJournalWaitResult, DiagnosticJournalWaitResultSchema, readDiagnosticJournalLockDiagnosis, } from '../application/diagnostic-journal-contract.js';
|
|
5
|
+
export { type DirectoryInbox, type DirectoryInboxConfig, type DirectoryInboxDelivery, type DirectoryInboxRejection, type DirectoryInboxRejectionReason, DirectoryInboxRejectionReasonSchema, type DirectoryInboxResource, type DirectoryInboxState, DirectoryInboxStateSchema, } from '../application/directory-inbox-contract.js';
|
|
5
6
|
export { type ApplicationEventSink, type ApplicationEventSinkConfig, type ApplicationLifecycleEvent, ApplicationLifecycleEventSchema, applicationLifecycleEvent, createApplicationEventSink, } from '../application/events.js';
|
|
6
7
|
export { type ApplicationHealthHandlerOptions, ApplicationHealthHandlerOptionsSchema, type ApplicationOperationalHandlers, type ApplicationOperationalHandlersOptions, ApplicationOperationalHandlersOptionsSchema, createApplicationHealthHandler, createApplicationOperationalHandlers, } from '../application/health.js';
|
|
7
8
|
export { createApplication } from '../application/kernel.js';
|
|
@@ -10,7 +11,8 @@ export { defineKeyspace, type KeyspaceBackend, type KeyspaceChange, type Keyspac
|
|
|
10
11
|
export { type SqliteKeyspaceBackendConfig, sqliteKeyspaceBackend, } from '../application/keyspace-sqlite.js';
|
|
11
12
|
export { type ApplicationSnapshotSink, type ApplicationSnapshotSinkConfig, type ApplicationSnapshotSinkError, type ApplicationSnapshotSinkStatus, ApplicationSnapshotSinkStatusSchema, createApplicationSnapshotSink, type RevisionedApplicationSnapshot, } from '../application/latest-sink.js';
|
|
12
13
|
export { createNotificationOutbox, type DroppedNotification, type EnqueueNotification, type NotificationFailureClassification, type NotificationOutbox, type NotificationOutboxConfig, type NotificationOutboxItem, type NotificationOutboxReceipt, type NotificationOutboxResource, type NotificationOutboxResourceConfig, type NotificationOutboxState, type NotificationSend, notificationOutboxResource, notificationOutboxStateSchema, } from '../application/notification-outbox.js';
|
|
13
|
-
export { createProcessLifecycleLedger, type LifecycleLedgerResource, type LifecycleLedgerResourceConfig,
|
|
14
|
+
export { createProcessLifecycleLedger, type LifecycleLedgerResource, type LifecycleLedgerResourceConfig, lifecycleLedgerResource, type ProcessLifecycleLedger, type ProcessLifecycleLedgerConfig, } from '../application/process-lifecycle.js';
|
|
15
|
+
export { type DrainingFact, type LifecycleRun, LifecycleRunSchema, type LifecycleState, LifecycleStateSchema, type LifecycleTermination, LifecycleTerminationSchema, type LifecycleTransition, type PreviousExit, PreviousExitSchema, type ProcessLifecycleFact, type ReadyFact, type SameVersionOverlap, type ShutdownFact, type StartFact, type TransitionRunInput, type TransitionShutdownInput, type TransitionStartInput, transitionProcessDraining, transitionProcessReady, transitionProcessShutdown, transitionProcessStart, } from '../application/process-lifecycle-transitions.js';
|
|
14
16
|
export { defineManagedResource, type ManagedResource, type ManagedResourceContext, type ManagedResourceDependency, type ManagedResourcePublished, type ManagedResourcePublishesNoValue, type ManagedResourceStartResult, managedResourceDependencyId, } from '../application/resource.js';
|
|
15
17
|
export { createRevisionSignal, type RevisionSignal, type RevisionSignalAdvanceResult, RevisionSignalAdvanceResultSchema, type RevisionSignalClock, type RevisionSignalConfig, type RevisionSignalSnapshot, RevisionSignalSnapshotSchema, type RevisionSignalState, RevisionSignalStateSchema, type RevisionSignalTimer, type RevisionSignalWaitOptions, type RevisionSignalWaitOutcome, RevisionSignalWaitOutcomeSchema, type RevisionSignalWaitResult, RevisionSignalWaitResultSchema, } from '../application/revision-signal.js';
|
|
16
18
|
export { createManagedSchedule, type ManagedSchedule, type ManagedScheduleClock, type ManagedScheduleConfig, type ManagedScheduleDescriptor, ManagedScheduleDescriptorSchema, type ManagedScheduleErrorPolicy, ManagedScheduleErrorPolicySchema, type ManagedScheduleOverlap, ManagedScheduleOverlapSchema, type ManagedScheduleRunContext, type ManagedScheduleStatus, ManagedScheduleStatusSchema, type ManagedScheduleTimer, } from '../application/schedule.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/entrypoints/application.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/entrypoints/application.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,10 @@ import {
|
|
|
14
14
|
createApplicationSnapshotSink,
|
|
15
15
|
createManagedSchedule
|
|
16
16
|
} from "../index-ensd0r74.js";
|
|
17
|
+
import {
|
|
18
|
+
DirectoryInboxRejectionReasonSchema,
|
|
19
|
+
DirectoryInboxStateSchema
|
|
20
|
+
} from "../index-5jrd0yng.js";
|
|
17
21
|
import {
|
|
18
22
|
DiagnosticJournalCloseResultSchema,
|
|
19
23
|
DiagnosticJournalFailurePhaseSchema,
|
|
@@ -1068,21 +1072,28 @@ function notificationOutboxResource(outbox, config = {}) {
|
|
|
1068
1072
|
});
|
|
1069
1073
|
}
|
|
1070
1074
|
// src/application/process-lifecycle.ts
|
|
1075
|
+
import { z as z7 } from "zod";
|
|
1076
|
+
|
|
1077
|
+
// src/application/process-lifecycle-transitions.ts
|
|
1071
1078
|
import { z as z6 } from "zod";
|
|
1072
1079
|
var LifecycleTerminationSchema = z6.enum([
|
|
1073
1080
|
"active",
|
|
1081
|
+
"draining",
|
|
1074
1082
|
"clean",
|
|
1075
1083
|
"forced",
|
|
1084
|
+
"startup-failed",
|
|
1076
1085
|
"hot-reload",
|
|
1077
1086
|
"abnormal"
|
|
1078
1087
|
]);
|
|
1088
|
+
var timestamp = z6.string().datetime({ offset: true });
|
|
1079
1089
|
var LifecycleRunSchema = z6.object({
|
|
1080
1090
|
runId: z6.string().min(1).max(128),
|
|
1081
1091
|
pid: z6.number().int().positive(),
|
|
1082
1092
|
version: z6.string().min(1).max(256),
|
|
1083
|
-
startedAt:
|
|
1084
|
-
readyAt:
|
|
1085
|
-
|
|
1093
|
+
startedAt: timestamp,
|
|
1094
|
+
readyAt: timestamp.nullable(),
|
|
1095
|
+
unavailableAt: timestamp.nullable().default(null),
|
|
1096
|
+
stoppedAt: timestamp.nullable(),
|
|
1086
1097
|
termination: LifecycleTerminationSchema
|
|
1087
1098
|
}).strict();
|
|
1088
1099
|
var LifecycleStateSchema = z6.object({
|
|
@@ -1094,17 +1105,20 @@ var PreviousExitSchema = z6.enum([
|
|
|
1094
1105
|
"hot-reload",
|
|
1095
1106
|
"clean",
|
|
1096
1107
|
"forced",
|
|
1108
|
+
"startup-failed",
|
|
1097
1109
|
"handoff",
|
|
1098
1110
|
"abnormal"
|
|
1099
1111
|
]);
|
|
1100
1112
|
var emptyState = () => ({ schemaVersion: 1, runs: [] });
|
|
1101
1113
|
var epoch = (value) => Date.parse(value);
|
|
1102
1114
|
var elapsed = (later, earlier) => Math.max(0, epoch(later) - epoch(earlier));
|
|
1103
|
-
|
|
1115
|
+
var isOpenRun = (run) => run.termination === "active" || run.termination === "draining";
|
|
1116
|
+
function normalizeLifecycleState(state, retain) {
|
|
1104
1117
|
const parsed = LifecycleStateSchema.parse(state ?? emptyState());
|
|
1105
1118
|
const runs = [...parsed.runs];
|
|
1106
1119
|
for (let index = runs.length - 1;runs.length > retain && index >= 0; index -= 1) {
|
|
1107
|
-
|
|
1120
|
+
const run = runs[index];
|
|
1121
|
+
if (run && !isOpenRun(run))
|
|
1108
1122
|
runs.splice(index, 1);
|
|
1109
1123
|
}
|
|
1110
1124
|
return { schemaVersion: 1, runs: runs.slice(0, retain) };
|
|
@@ -1113,15 +1127,45 @@ var UNKNOWN_VERSION = "unknown";
|
|
|
1113
1127
|
function isVersionChange(previous, next) {
|
|
1114
1128
|
return previous !== UNKNOWN_VERSION && next !== UNKNOWN_VERSION && previous !== next;
|
|
1115
1129
|
}
|
|
1130
|
+
var RetainSchema = z6.number().int().min(1).max(1000);
|
|
1131
|
+
function previousExitOf(previous, run, overlap) {
|
|
1132
|
+
if (!previous)
|
|
1133
|
+
return "first-boot";
|
|
1134
|
+
const ended = previous.termination;
|
|
1135
|
+
if (ended !== "active" && ended !== "draining")
|
|
1136
|
+
return ended;
|
|
1137
|
+
if (previous.pid === run.pid)
|
|
1138
|
+
return "hot-reload";
|
|
1139
|
+
if (isVersionChange(previous.version, run.version) || overlap === "handoff")
|
|
1140
|
+
return "handoff";
|
|
1141
|
+
return previous.readyAt === null ? "startup-failed" : "abnormal";
|
|
1142
|
+
}
|
|
1143
|
+
function closeAbandoned(candidate, previous, previousExit, run, overlap) {
|
|
1144
|
+
if (!isOpenRun(candidate))
|
|
1145
|
+
return candidate;
|
|
1146
|
+
const closed = { ...candidate, stoppedAt: run.startedAt };
|
|
1147
|
+
if (candidate.pid === run.pid)
|
|
1148
|
+
return { ...closed, termination: "hot-reload" };
|
|
1149
|
+
if (overlap === "handoff")
|
|
1150
|
+
return candidate;
|
|
1151
|
+
if (candidate.runId === previous?.runId && previousExit === "handoff")
|
|
1152
|
+
return candidate;
|
|
1153
|
+
return {
|
|
1154
|
+
...closed,
|
|
1155
|
+
termination: candidate.readyAt === null ? "startup-failed" : "abnormal"
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1116
1158
|
function transitionProcessStart(source, input) {
|
|
1117
|
-
const retain =
|
|
1118
|
-
const
|
|
1159
|
+
const retain = RetainSchema.parse(input.retain ?? 20);
|
|
1160
|
+
const overlap = input.sameVersionOverlap ?? "abnormal";
|
|
1161
|
+
const state = normalizeLifecycleState(source, 1000);
|
|
1119
1162
|
const run = LifecycleRunSchema.parse({
|
|
1120
1163
|
runId: input.runId,
|
|
1121
1164
|
pid: input.pid,
|
|
1122
1165
|
version: input.version,
|
|
1123
1166
|
startedAt: input.now,
|
|
1124
1167
|
readyAt: null,
|
|
1168
|
+
unavailableAt: null,
|
|
1125
1169
|
stoppedAt: null,
|
|
1126
1170
|
termination: "active"
|
|
1127
1171
|
});
|
|
@@ -1129,31 +1173,10 @@ function transitionProcessStart(source, input) {
|
|
|
1129
1173
|
throw new Error(`[stitchkit] lifecycle run id already exists: ${run.runId}`);
|
|
1130
1174
|
}
|
|
1131
1175
|
const previous = state.runs[0] ?? null;
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
downtimeMs = elapsed(run.startedAt, previous.stoppedAt);
|
|
1137
|
-
} else if (previous) {
|
|
1138
|
-
if (previous.pid === run.pid)
|
|
1139
|
-
previousExit = "hot-reload";
|
|
1140
|
-
else if (isVersionChange(previous.version, run.version))
|
|
1141
|
-
previousExit = "handoff";
|
|
1142
|
-
else
|
|
1143
|
-
previousExit = input.sameVersionOverlap ?? "abnormal";
|
|
1144
|
-
}
|
|
1145
|
-
const runs = state.runs.map((candidate) => {
|
|
1146
|
-
if (candidate.runId !== previous?.runId || candidate.termination !== "active")
|
|
1147
|
-
return candidate;
|
|
1148
|
-
if (previousExit === "hot-reload") {
|
|
1149
|
-
return { ...candidate, stoppedAt: run.startedAt, termination: "hot-reload" };
|
|
1150
|
-
}
|
|
1151
|
-
if (previousExit === "abnormal") {
|
|
1152
|
-
return { ...candidate, stoppedAt: run.startedAt, termination: "abnormal" };
|
|
1153
|
-
}
|
|
1154
|
-
return candidate;
|
|
1155
|
-
});
|
|
1156
|
-
const next = normalize({ schemaVersion: 1, runs: [run, ...runs] }, retain);
|
|
1176
|
+
const previousExit = previousExitOf(previous, run, overlap);
|
|
1177
|
+
const processGapMs = previous && !isOpenRun(previous) && previous.stoppedAt ? elapsed(run.startedAt, previous.stoppedAt) : null;
|
|
1178
|
+
const runs = state.runs.map((candidate) => closeAbandoned(candidate, previous, previousExit, run, overlap));
|
|
1179
|
+
const next = normalizeLifecycleState({ schemaVersion: 1, runs: [run, ...runs] }, retain);
|
|
1157
1180
|
return {
|
|
1158
1181
|
state: next,
|
|
1159
1182
|
fact: {
|
|
@@ -1167,15 +1190,30 @@ function transitionProcessStart(source, input) {
|
|
|
1167
1190
|
previousPid: previous?.pid ?? null,
|
|
1168
1191
|
previousVersion: previous?.version ?? null,
|
|
1169
1192
|
versionChanged: previous !== null && isVersionChange(previous.version, run.version),
|
|
1170
|
-
|
|
1193
|
+
processGapMs
|
|
1171
1194
|
}
|
|
1172
1195
|
};
|
|
1173
1196
|
}
|
|
1197
|
+
function findOpen(state, input) {
|
|
1198
|
+
return state.runs.find((run) => run.runId === input.runId && run.pid === input.pid && isOpenRun(run));
|
|
1199
|
+
}
|
|
1200
|
+
function unavailability(state, target, readyAt) {
|
|
1201
|
+
const older = state.runs.slice(state.runs.indexOf(target) + 1);
|
|
1202
|
+
const served = older.find((run) => run.readyAt !== null);
|
|
1203
|
+
if (!served)
|
|
1204
|
+
return { downtimeMs: null, unavailableSince: null };
|
|
1205
|
+
if (served.unavailableAt !== null) {
|
|
1206
|
+
return {
|
|
1207
|
+
downtimeMs: elapsed(readyAt, served.unavailableAt),
|
|
1208
|
+
unavailableSince: served.unavailableAt
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
return isOpenRun(served) ? { downtimeMs: 0, unavailableSince: null } : { downtimeMs: null, unavailableSince: null };
|
|
1212
|
+
}
|
|
1174
1213
|
function transitionProcessReady(source, input) {
|
|
1175
|
-
const
|
|
1176
|
-
const
|
|
1177
|
-
|
|
1178
|
-
if (!target) {
|
|
1214
|
+
const state = normalizeLifecycleState(source, input.retain ?? 20);
|
|
1215
|
+
const target = findOpen(state, input);
|
|
1216
|
+
if (target?.termination !== "active") {
|
|
1179
1217
|
return {
|
|
1180
1218
|
state,
|
|
1181
1219
|
fact: {
|
|
@@ -1184,6 +1222,8 @@ function transitionProcessReady(source, input) {
|
|
|
1184
1222
|
pid: input.pid,
|
|
1185
1223
|
readyAt: input.now,
|
|
1186
1224
|
startupMs: 0,
|
|
1225
|
+
downtimeMs: null,
|
|
1226
|
+
unavailableSince: null,
|
|
1187
1227
|
recorded: false
|
|
1188
1228
|
}
|
|
1189
1229
|
};
|
|
@@ -1200,14 +1240,45 @@ function transitionProcessReady(source, input) {
|
|
|
1200
1240
|
pid: target.pid,
|
|
1201
1241
|
readyAt,
|
|
1202
1242
|
startupMs: elapsed(readyAt, target.startedAt),
|
|
1243
|
+
...unavailability(state, target, readyAt),
|
|
1203
1244
|
recorded: target.readyAt === null
|
|
1204
1245
|
}
|
|
1205
1246
|
};
|
|
1206
1247
|
}
|
|
1248
|
+
function transitionProcessDraining(source, input) {
|
|
1249
|
+
const state = normalizeLifecycleState(source, input.retain ?? 20);
|
|
1250
|
+
const target = findOpen(state, input);
|
|
1251
|
+
if (target?.termination !== "active") {
|
|
1252
|
+
return {
|
|
1253
|
+
state,
|
|
1254
|
+
fact: {
|
|
1255
|
+
type: "draining",
|
|
1256
|
+
runId: input.runId,
|
|
1257
|
+
pid: input.pid,
|
|
1258
|
+
unavailableAt: target ? target.unavailableAt : null,
|
|
1259
|
+
recorded: false
|
|
1260
|
+
}
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
const unavailableAt = target.readyAt === null ? null : input.now;
|
|
1264
|
+
return {
|
|
1265
|
+
state: {
|
|
1266
|
+
schemaVersion: 1,
|
|
1267
|
+
runs: state.runs.map((run) => run.runId === target.runId ? { ...run, termination: "draining", unavailableAt } : run)
|
|
1268
|
+
},
|
|
1269
|
+
fact: {
|
|
1270
|
+
type: "draining",
|
|
1271
|
+
runId: target.runId,
|
|
1272
|
+
pid: target.pid,
|
|
1273
|
+
unavailableAt,
|
|
1274
|
+
recorded: true
|
|
1275
|
+
}
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1207
1278
|
function transitionProcessShutdown(source, input) {
|
|
1208
|
-
const state =
|
|
1209
|
-
const target = state
|
|
1210
|
-
const
|
|
1279
|
+
const state = normalizeLifecycleState(source, input.retain ?? 20);
|
|
1280
|
+
const target = findOpen(state, input);
|
|
1281
|
+
const requested = input.forced ? "forced" : "clean";
|
|
1211
1282
|
if (!target) {
|
|
1212
1283
|
return {
|
|
1213
1284
|
state,
|
|
@@ -1217,15 +1288,17 @@ function transitionProcessShutdown(source, input) {
|
|
|
1217
1288
|
pid: input.pid,
|
|
1218
1289
|
stoppedAt: input.now,
|
|
1219
1290
|
uptimeMs: null,
|
|
1220
|
-
termination,
|
|
1291
|
+
termination: requested,
|
|
1221
1292
|
recorded: false
|
|
1222
1293
|
}
|
|
1223
1294
|
};
|
|
1224
1295
|
}
|
|
1296
|
+
const termination = target.readyAt === null ? "startup-failed" : requested;
|
|
1297
|
+
const unavailableAt = target.unavailableAt ?? (target.readyAt === null ? null : input.now);
|
|
1225
1298
|
return {
|
|
1226
1299
|
state: {
|
|
1227
1300
|
schemaVersion: 1,
|
|
1228
|
-
runs: state.runs.map((run) => run.runId === target.runId ? { ...run, stoppedAt: input.now, termination } : run)
|
|
1301
|
+
runs: state.runs.map((run) => run.runId === target.runId ? { ...run, unavailableAt, stoppedAt: input.now, termination } : run)
|
|
1229
1302
|
},
|
|
1230
1303
|
fact: {
|
|
1231
1304
|
type: "stopped",
|
|
@@ -1238,10 +1311,12 @@ function transitionProcessShutdown(source, input) {
|
|
|
1238
1311
|
}
|
|
1239
1312
|
};
|
|
1240
1313
|
}
|
|
1314
|
+
|
|
1315
|
+
// src/application/process-lifecycle.ts
|
|
1241
1316
|
function createProcessLifecycleLedger(config) {
|
|
1242
1317
|
const clock = config.clock ?? (() => new Date);
|
|
1243
|
-
const pid =
|
|
1244
|
-
const retain =
|
|
1318
|
+
const pid = z7.number().int().positive().parse(config.pid ?? process.pid);
|
|
1319
|
+
const retain = z7.number().int().min(1).max(1000).parse(config.retain ?? 20);
|
|
1245
1320
|
const configuredRunId = config.runId;
|
|
1246
1321
|
const nextRunId = typeof configuredRunId === "function" ? configuredRunId : configuredRunId === undefined ? () => crypto.randomUUID() : () => configuredRunId;
|
|
1247
1322
|
let runId = nextRunId();
|
|
@@ -1285,6 +1360,20 @@ function createProcessLifecycleLedger(config) {
|
|
|
1285
1360
|
publish(fact);
|
|
1286
1361
|
return fact;
|
|
1287
1362
|
},
|
|
1363
|
+
async recordDraining() {
|
|
1364
|
+
const fact = await config.store.update((state) => {
|
|
1365
|
+
const transition = transitionProcessDraining(state, {
|
|
1366
|
+
runId,
|
|
1367
|
+
pid,
|
|
1368
|
+
now: clock().toISOString(),
|
|
1369
|
+
retain
|
|
1370
|
+
});
|
|
1371
|
+
return { state: transition.state, result: transition.fact };
|
|
1372
|
+
});
|
|
1373
|
+
if (fact.recorded)
|
|
1374
|
+
publish(fact);
|
|
1375
|
+
return fact;
|
|
1376
|
+
},
|
|
1288
1377
|
async recordShutdown(input) {
|
|
1289
1378
|
const fact = await config.store.update((state) => {
|
|
1290
1379
|
const transition = transitionProcessShutdown(state, {
|
|
@@ -1301,11 +1390,11 @@ function createProcessLifecycleLedger(config) {
|
|
|
1301
1390
|
return fact;
|
|
1302
1391
|
},
|
|
1303
1392
|
async current() {
|
|
1304
|
-
const state =
|
|
1393
|
+
const state = normalizeLifecycleState(await config.store.read(), retain);
|
|
1305
1394
|
return state.runs.find((run) => run.runId === runId && run.pid === pid) ?? null;
|
|
1306
1395
|
},
|
|
1307
1396
|
async runs() {
|
|
1308
|
-
return
|
|
1397
|
+
return normalizeLifecycleState(await config.store.read(), retain).runs;
|
|
1309
1398
|
},
|
|
1310
1399
|
subscribe(listener) {
|
|
1311
1400
|
listeners.add(listener);
|
|
@@ -1340,6 +1429,9 @@ function lifecycleLedgerResource(ledger, config) {
|
|
|
1340
1429
|
async activate() {
|
|
1341
1430
|
await ledger.recordReady();
|
|
1342
1431
|
},
|
|
1432
|
+
async stopAdmission() {
|
|
1433
|
+
await ledger.recordDraining();
|
|
1434
|
+
},
|
|
1343
1435
|
async close() {
|
|
1344
1436
|
await stop(false);
|
|
1345
1437
|
},
|
|
@@ -1349,27 +1441,27 @@ function lifecycleLedgerResource(ledger, config) {
|
|
|
1349
1441
|
});
|
|
1350
1442
|
}
|
|
1351
1443
|
// src/application/revision-signal.ts
|
|
1352
|
-
import { z as
|
|
1353
|
-
var NonNegativeSafeIntegerSchema =
|
|
1354
|
-
var PositiveSafeIntegerSchema2 =
|
|
1355
|
-
var TimerDelaySchema =
|
|
1356
|
-
var RevisionSignalStateSchema =
|
|
1357
|
-
var RevisionSignalWaitOutcomeSchema =
|
|
1444
|
+
import { z as z8 } from "zod";
|
|
1445
|
+
var NonNegativeSafeIntegerSchema = z8.number().int().nonnegative().safe();
|
|
1446
|
+
var PositiveSafeIntegerSchema2 = z8.number().int().positive().safe();
|
|
1447
|
+
var TimerDelaySchema = z8.number().int().positive().max(2147483647);
|
|
1448
|
+
var RevisionSignalStateSchema = z8.enum(["open", "closed"]);
|
|
1449
|
+
var RevisionSignalWaitOutcomeSchema = z8.enum([
|
|
1358
1450
|
"changed",
|
|
1359
1451
|
"timed-out",
|
|
1360
1452
|
"aborted",
|
|
1361
1453
|
"closed",
|
|
1362
1454
|
"capacity"
|
|
1363
1455
|
]);
|
|
1364
|
-
var RevisionSignalWaitResultSchema =
|
|
1456
|
+
var RevisionSignalWaitResultSchema = z8.object({
|
|
1365
1457
|
outcome: RevisionSignalWaitOutcomeSchema,
|
|
1366
1458
|
revision: NonNegativeSafeIntegerSchema
|
|
1367
1459
|
}).strict().readonly();
|
|
1368
|
-
var RevisionSignalAdvanceResultSchema =
|
|
1369
|
-
outcome:
|
|
1460
|
+
var RevisionSignalAdvanceResultSchema = z8.object({
|
|
1461
|
+
outcome: z8.enum(["advanced", "closed"]),
|
|
1370
1462
|
revision: NonNegativeSafeIntegerSchema
|
|
1371
1463
|
}).strict().readonly();
|
|
1372
|
-
var RevisionSignalSnapshotSchema =
|
|
1464
|
+
var RevisionSignalSnapshotSchema = z8.object({
|
|
1373
1465
|
state: RevisionSignalStateSchema,
|
|
1374
1466
|
revision: NonNegativeSafeIntegerSchema,
|
|
1375
1467
|
pending: NonNegativeSafeIntegerSchema,
|
|
@@ -1919,6 +2011,7 @@ export {
|
|
|
1919
2011
|
transitionProcessStart,
|
|
1920
2012
|
transitionProcessShutdown,
|
|
1921
2013
|
transitionProcessReady,
|
|
2014
|
+
transitionProcessDraining,
|
|
1922
2015
|
sqliteKeyspaceBackend,
|
|
1923
2016
|
readDiagnosticJournalLockDiagnosis,
|
|
1924
2017
|
projectApplicationStatus,
|
|
@@ -1964,6 +2057,8 @@ export {
|
|
|
1964
2057
|
LifecycleTerminationSchema,
|
|
1965
2058
|
LifecycleStateSchema,
|
|
1966
2059
|
LifecycleRunSchema,
|
|
2060
|
+
DirectoryInboxStateSchema,
|
|
2061
|
+
DirectoryInboxRejectionReasonSchema,
|
|
1967
2062
|
DiagnosticJournalWaitResultSchema,
|
|
1968
2063
|
DiagnosticJournalSubmitResultSchema,
|
|
1969
2064
|
DiagnosticJournalStatusSchema,
|