@overkill-dev/run 0.0.92 → 0.0.94
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/baselines/calibration-reference.js +1 -1
- package/baselines/calibration-reference.js.map +1 -1
- package/baselines/performance-presentation.js +1 -1
- package/baselines/performance-presentation.js.map +1 -1
- package/baselines/performance-schema.js +1 -1
- package/baselines/performance-schema.js.map +1 -1
- package/bench/calibration-evidence.js +1 -1
- package/bench/calibration-evidence.js.map +1 -1
- package/config/config.d.ts +3 -1
- package/config/config.d.ts.map +1 -1
- package/config/config.js +10 -11
- package/config/config.js.map +1 -1
- package/config/defaults.js +4 -0
- package/config/defaults.js.map +1 -1
- package/config/history-policy.d.ts +15 -0
- package/config/history-policy.d.ts.map +1 -0
- package/config/history-policy.js +26 -0
- package/config/history-policy.js.map +1 -0
- package/config/normalized-microtest-schema.js +1 -0
- package/config/normalized-microtest-schema.js.map +1 -1
- package/config/profile-normalization.js +4 -1
- package/config/profile-normalization.js.map +1 -1
- package/config/property-corpus.js +21 -0
- package/config/property-corpus.js.map +1 -0
- package/config/schema.d.ts +76 -0
- package/config/schema.d.ts.map +1 -1
- package/config/schema.js +8 -0
- package/config/schema.js.map +1 -1
- package/config/snapshot.js +6 -0
- package/config/snapshot.js.map +1 -1
- package/config/types.d.ts +24 -0
- package/config/types.d.ts.map +1 -1
- package/config/validation.js +4 -0
- package/config/validation.js.map +1 -1
- package/package.json +13 -3
- package/packages/run/command-line.entry-point.d.ts +1 -1
- package/packages/run/command-line.entry-point.d.ts.map +1 -1
- package/packages/run/command-line.entry-point.js +5 -2
- package/packages/run/command-line.entry-point.js.map +1 -1
- package/packages/run/config.entry-point.d.ts +1 -0
- package/packages/run/config.entry-point.d.ts.map +1 -1
- package/packages/run/run.entry-point.d.ts +5 -1
- package/packages/run/run.entry-point.d.ts.map +1 -1
- package/packages/run/run.entry-point.js +2 -1
- package/packages/run/run.entry-point.js.map +1 -1
- package/readme.md +120 -1
- package/reporters/failure-summary.js +29 -0
- package/reporters/failure-summary.js.map +1 -1
- package/reporters/human-reporter-rendering.js +5 -1
- package/reporters/human-reporter-rendering.js.map +1 -1
- package/run/assertion-result-schema.js +1 -1
- package/run/assertion-result-schema.js.map +1 -1
- package/run/attachment-record.js +13 -12
- package/run/attachment-record.js.map +1 -1
- package/run/attachment-run.js +18 -7
- package/run/attachment-run.js.map +1 -1
- package/run/benchmark-result-schema.js +1 -1
- package/run/benchmark-result-schema.js.map +1 -1
- package/run/collected-run-execution.js +4 -26
- package/run/collected-run-execution.js.map +1 -1
- package/run/collected-run-invocation.js +39 -0
- package/run/collected-run-invocation.js.map +1 -0
- package/run/collected-run-plan-schema.js +1 -1
- package/run/collected-run-plan-schema.js.map +1 -1
- package/run/collected-run.js +4 -3
- package/run/collected-run.js.map +1 -1
- package/run/command-line-command-namespace.d.ts +2 -0
- package/run/command-line-command-namespace.d.ts.map +1 -1
- package/run/command-line-command-namespace.js +35 -0
- package/run/command-line-command-namespace.js.map +1 -1
- package/run/command-line-command.d.ts +5 -0
- package/run/command-line-command.d.ts.map +1 -1
- package/run/command-line-config.js +2 -0
- package/run/command-line-config.js.map +1 -1
- package/run/command-line-execution.js +5 -1
- package/run/command-line-execution.js.map +1 -1
- package/run/command-line-runner.d.ts +2 -1
- package/run/command-line-runner.d.ts.map +1 -1
- package/run/command-line-runner.js +2 -1
- package/run/command-line-runner.js.map +1 -1
- package/run/compact-history-schema.d.ts +20 -0
- package/run/compact-history-schema.d.ts.map +1 -0
- package/run/compact-history-schema.js +32 -0
- package/run/compact-history-schema.js.map +1 -0
- package/run/compact-history.js +100 -0
- package/run/compact-history.js.map +1 -0
- package/run/coverage-run-record.js +2 -9
- package/run/coverage-run-record.js.map +1 -1
- package/run/duration-history-schema.js +3 -1
- package/run/duration-history-schema.js.map +1 -1
- package/run/duration-history-storage.js +170 -0
- package/run/duration-history-storage.js.map +1 -0
- package/run/duration-history-types.js +2 -0
- package/run/duration-history-types.js.map +1 -0
- package/run/duration-history.js +24 -92
- package/run/duration-history.js.map +1 -1
- package/run/execution-session-collected.js +1 -1
- package/run/execution-session-collected.js.map +1 -1
- package/run/execution-session-supervised.js +1 -1
- package/run/execution-session-supervised.js.map +1 -1
- package/run/freeze-run-policy.js +1 -0
- package/run/freeze-run-policy.js.map +1 -1
- package/run/frozen-policy-validation.js +1 -0
- package/run/frozen-policy-validation.js.map +1 -1
- package/run/frozen-run-policy-schema.js +3 -0
- package/run/frozen-run-policy-schema.js.map +1 -1
- package/run/frozen-run-policy.d.ts.map +1 -1
- package/run/frozen-run-policy.js +1 -0
- package/run/frozen-run-policy.js.map +1 -1
- package/run/history-commands.d.ts +4 -0
- package/run/history-commands.d.ts.map +1 -0
- package/run/history-commands.js +76 -0
- package/run/history-commands.js.map +1 -0
- package/run/history-confirmation.js +33 -0
- package/run/history-confirmation.js.map +1 -0
- package/run/history-lock-acquisition.js +59 -0
- package/run/history-lock-acquisition.js.map +1 -0
- package/run/history-maintenance-budget.js +35 -0
- package/run/history-maintenance-budget.js.map +1 -0
- package/run/history-maintenance.js +21 -0
- package/run/history-maintenance.js.map +1 -0
- package/run/history-outcomes.js +78 -0
- package/run/history-outcomes.js.map +1 -0
- package/run/history-pruning.js +104 -0
- package/run/history-pruning.js.map +1 -0
- package/run/history-reader.js +32 -0
- package/run/history-reader.js.map +1 -0
- package/run/history-record.js +48 -0
- package/run/history-record.js.map +1 -0
- package/run/history-repair.js +158 -0
- package/run/history-repair.js.map +1 -0
- package/run/history-retention-metadata.js +54 -0
- package/run/history-retention-metadata.js.map +1 -0
- package/run/history-retention-records.js +85 -0
- package/run/history-retention-records.js.map +1 -0
- package/run/history-state-access.js +161 -0
- package/run/history-state-access.js.map +1 -0
- package/run/history-state-error.js +35 -0
- package/run/history-state-error.js.map +1 -0
- package/run/history-storage-types.d.ts +13 -0
- package/run/history-storage-types.d.ts.map +1 -0
- package/run/history-storage.js +55 -0
- package/run/history-storage.js.map +1 -0
- package/run/history-types.d.ts +40 -0
- package/run/history-types.d.ts.map +1 -0
- package/run/history.d.ts +3 -0
- package/run/history.d.ts.map +1 -0
- package/run/history.js +97 -0
- package/run/history.js.map +1 -0
- package/run/local-run-collection.js +31 -0
- package/run/local-run-collection.js.map +1 -0
- package/run/node-history-storage.js +107 -0
- package/run/node-history-storage.js.map +1 -0
- package/run/node-run-execution.js +6 -0
- package/run/node-run-execution.js.map +1 -1
- package/run/prepared-run.js +42 -0
- package/run/prepared-run.js.map +1 -0
- package/run/property-corpus-cache.js +85 -0
- package/run/property-corpus-cache.js.map +1 -0
- package/run/property-corpus-execution.js +69 -0
- package/run/property-corpus-execution.js.map +1 -0
- package/run/property-corpus-storage.js +86 -0
- package/run/property-corpus-storage.js.map +1 -0
- package/run/property-evidence-schema.js +48 -0
- package/run/property-evidence-schema.js.map +1 -0
- package/run/recorded-coverage-run.js +2 -12
- package/run/recorded-coverage-run.js.map +1 -1
- package/run/recorded-run.js +32 -0
- package/run/recorded-run.js.map +1 -0
- package/run/replay-command.js +5 -0
- package/run/replay-command.js.map +1 -0
- package/run/reporter-event-schema.js +4 -1
- package/run/reporter-event-schema.js.map +1 -1
- package/run/request-snapshot.js +1 -0
- package/run/request-snapshot.js.map +1 -1
- package/run/run-artifact-id-schema.js +1 -1
- package/run/run-artifact-id-schema.js.map +1 -1
- package/run/run-artifact-schema.d.ts.map +1 -1
- package/run/run-artifact-schema.js +3 -1
- package/run/run-artifact-schema.js.map +1 -1
- package/run/run-collected-resolution.js +3 -3
- package/run/run-collected-resolution.js.map +1 -1
- package/run/run-command-schema.js +8 -0
- package/run/run-command-schema.js.map +1 -1
- package/run/run-empty-shard.js.map +1 -1
- package/run/run-engine-primitives.d.ts.map +1 -1
- package/run/run-execution.js +26 -50
- package/run/run-execution.js.map +1 -1
- package/run/run-facts.js +54 -1
- package/run/run-facts.js.map +1 -1
- package/run/run-if-main.d.ts.map +1 -1
- package/run/run-if-main.js +5 -0
- package/run/run-if-main.js.map +1 -1
- package/run/run-in-process-execution.js.map +1 -1
- package/run/run-isolated-process.js +12 -3
- package/run/run-isolated-process.js.map +1 -1
- package/run/run-local-command.js +14 -33
- package/run/run-local-command.js.map +1 -1
- package/run/run-local-coverage.js +2 -1
- package/run/run-local-coverage.js.map +1 -1
- package/run/run-local-execution.js +3 -0
- package/run/run-local-execution.js.map +1 -1
- package/run/run-local-planning.js +5 -5
- package/run/run-local-planning.js.map +1 -1
- package/run/run-local-resolution.js +0 -4
- package/run/run-local-resolution.js.map +1 -1
- package/run/run-operations.d.ts.map +1 -1
- package/run/run-operations.js +1 -0
- package/run/run-operations.js.map +1 -1
- package/run/run-orchestrator-dependencies.d.ts +4 -2
- package/run/run-orchestrator-dependencies.d.ts.map +1 -1
- package/run/run-profile-facts.js +12 -0
- package/run/run-profile-facts.js.map +1 -1
- package/run/run-record-input.js +21 -0
- package/run/run-record-input.js.map +1 -1
- package/run/run-record-storage.js +15 -2
- package/run/run-record-storage.js.map +1 -1
- package/run/run-record.js +66 -19
- package/run/run-record.js.map +1 -1
- package/run/run-result-schema.d.ts +2 -0
- package/run/run-result-schema.d.ts.map +1 -1
- package/run/run-result-schema.js +11 -1
- package/run/run-result-schema.js.map +1 -1
- package/run/run-selection-filters.js +1 -1
- package/run/run-selection-filters.js.map +1 -1
- package/run/run-selection-schema.js +1 -1
- package/run/run-selection-schema.js.map +1 -1
- package/run/run-state-finalization.js +22 -0
- package/run/run-state-finalization.js.map +1 -0
- package/run/run-supervised-finalization.js +1 -1
- package/run/run-supervised-finalization.js.map +1 -1
- package/run/run-supervised-process.js +2 -1
- package/run/run-supervised-process.js.map +1 -1
- package/run/run-support.js +1 -19
- package/run/run-support.js.map +1 -1
- package/run/run-types.d.ts +14 -8
- package/run/run-types.d.ts.map +1 -1
- package/run/run-types.js.map +1 -1
- package/run/run-validation.js +3 -0
- package/run/run-validation.js.map +1 -1
- package/run/runner-result.js +10 -0
- package/run/runner-result.js.map +1 -0
- package/run/runtime-attachment-boundary.js +3 -3
- package/run/runtime-attachment-boundary.js.map +1 -1
- package/run/supervised-child-transport.js +19 -0
- package/run/supervised-child-transport.js.map +1 -1
- package/run/supervised-child.js +6 -2
- package/run/supervised-child.js.map +1 -1
- package/run/supervised-protocol-schema.js +3 -2
- package/run/supervised-protocol-schema.js.map +1 -1
- package/run/supervised-protocol.js +3 -0
- package/run/supervised-protocol.js.map +1 -1
- package/run/supervised-run-runtime.js +5 -0
- package/run/supervised-run-runtime.js.map +1 -1
- package/run/supervised-run-state.js +10 -1
- package/run/supervised-run-state.js.map +1 -1
- package/run/supervised-run.js +6 -20
- package/run/supervised-run.js.map +1 -1
- package/run/worker-pool-host-protocol-schema.js +1 -1
- package/run/worker-pool-host-protocol-schema.js.map +1 -1
- package/run/worker-pool-placement-planning.js.map +1 -1
- package/run/worker-pool-run.js +1 -1
- package/run/worker-pool-run.js.map +1 -1
- package/run/worker-pool-task-schema.js +1 -1
- package/run/worker-pool-task-schema.js.map +1 -1
- package/software-bill-of-materials.cyclonedx.json +26 -9
- package/engine/identity-schema.js +0 -38
- package/engine/identity-schema.js.map +0 -1
- package/run/attachment-eligibility.js +0 -37
- package/run/attachment-eligibility.js.map +0 -1
- package/run/duration-history.d.ts +0 -6
- package/run/duration-history.d.ts.map +0 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { emptyCompactHistory, ingestCompactRecord, retainCompactHistory } from "./compact-history.js";
|
|
4
|
+
import { compactHistorySchema } from "./compact-history-schema.js";
|
|
5
|
+
import { historyRecordSchema } from "./history-record.js";
|
|
6
|
+
import { historyStateError, assertSupportedHistoryVersion, UnsupportedHistoryVersionError } from "./history-state-error.js";
|
|
7
|
+
import { recordDurationContributions } from "./history-outcomes.js";
|
|
8
|
+
import { durationHistoryStateSchema, durationStatePath, emptyDurationState, ingestDurationState, readDurationState } from "./duration-history-storage.js";
|
|
9
|
+
const automaticRepairBudgetMilliseconds = 2000;
|
|
10
|
+
function assertBudget(deadline) {
|
|
11
|
+
if (performance.now() > deadline) {
|
|
12
|
+
throw historyStateError('Automatic history repair exceeded its two-second budget.');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const legacyIndexSchema = compactHistorySchema.extend({ version: z.literal(0) });
|
|
16
|
+
function recoverIndexValue(source) {
|
|
17
|
+
const value = JSON.parse(source);
|
|
18
|
+
const legacy = legacyIndexSchema.safeParse(value);
|
|
19
|
+
return legacy.success ? { ...legacy.data, version: 1 } : compactHistorySchema.parse(value);
|
|
20
|
+
}
|
|
21
|
+
async function recoverIndex(store, context) {
|
|
22
|
+
const source = await store.read(path.join(context.directory, 'history', 'index.json'));
|
|
23
|
+
if (source === null) {
|
|
24
|
+
return { value: emptyCompactHistory(context.now), dataLoss: false, diagnostics: [] };
|
|
25
|
+
}
|
|
26
|
+
assertSupportedHistoryVersion(source, 1);
|
|
27
|
+
try {
|
|
28
|
+
return { value: recoverIndexValue(source), dataLoss: false, diagnostics: [] };
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (context.mode === 'automatic') {
|
|
32
|
+
throw historyStateError(error);
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
value: emptyCompactHistory(context.now),
|
|
36
|
+
dataLoss: true,
|
|
37
|
+
diagnostics: [
|
|
38
|
+
'Unreadable compact history was rebuilt. Pruned summaries, observations, and counters may be lost.'
|
|
39
|
+
]
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function durationRepairPart(store, context) {
|
|
44
|
+
const existing = await readDurationState(store, context.directory, context.now);
|
|
45
|
+
return { value: existing ?? emptyDurationState(context.now), dataLoss: false, diagnostics: [] };
|
|
46
|
+
}
|
|
47
|
+
async function recoverDurations(store, context) {
|
|
48
|
+
try {
|
|
49
|
+
return await durationRepairPart(store, context);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (context.mode === 'automatic' || error instanceof UnsupportedHistoryVersionError) {
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
value: emptyDurationState(context.now),
|
|
57
|
+
dataLoss: true,
|
|
58
|
+
diagnostics: ['Unreadable duration history was rebuilt. Samples without retained records may be lost.']
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function repairState(store, context) {
|
|
63
|
+
const [index, durations] = await Promise.all([recoverIndex(store, context), recoverDurations(store, context)]);
|
|
64
|
+
return {
|
|
65
|
+
index: index.value,
|
|
66
|
+
durations: durations.value,
|
|
67
|
+
dataLoss: index.dataLoss || durations.dataLoss,
|
|
68
|
+
diagnostics: [...index.diagnostics, ...durations.diagnostics]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function missingRecordFamily(state, record, context) {
|
|
72
|
+
if (context.mode === 'automatic') {
|
|
73
|
+
throw historyStateError(`Cannot recover test family for ${record.id}.`);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
...state,
|
|
77
|
+
index: ingestCompactRecord(state.index, record, { ...context, testFamily: null }),
|
|
78
|
+
dataLoss: true,
|
|
79
|
+
diagnostics: [
|
|
80
|
+
...state.diagnostics,
|
|
81
|
+
`Unresolved record ${record.id} has no recoverable test family; its summary could not be restored.`
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function recoverRecord(state, record, context) {
|
|
86
|
+
const previous = state.index.summaries.find(function matchingRun(value) {
|
|
87
|
+
return value.id === record.id;
|
|
88
|
+
});
|
|
89
|
+
const testFamily = record.facts?.execution.testFamily ?? previous?.testFamily;
|
|
90
|
+
const durations = record.status === 'completed'
|
|
91
|
+
? ingestDurationState(state.durations, recordDurationContributions(record), {
|
|
92
|
+
run: { id: record.id, startedAt: record.startedAt },
|
|
93
|
+
source: 'repair',
|
|
94
|
+
policy: context.policy,
|
|
95
|
+
now: context.now
|
|
96
|
+
})
|
|
97
|
+
: state.durations;
|
|
98
|
+
if (testFamily === undefined) {
|
|
99
|
+
return missingRecordFamily({ ...state, durations }, record, context);
|
|
100
|
+
}
|
|
101
|
+
return { ...state, durations, index: ingestCompactRecord(state.index, record, { ...context, testFamily }) };
|
|
102
|
+
}
|
|
103
|
+
async function rebuildRecords(store, context, paths, deadline) {
|
|
104
|
+
let state = await repairState(store, context);
|
|
105
|
+
for (const recordPath of paths) {
|
|
106
|
+
assertBudget(deadline);
|
|
107
|
+
const source = await store.read(recordPath);
|
|
108
|
+
if (source === null) {
|
|
109
|
+
throw historyStateError(`Record disappeared during repair: ${recordPath}`);
|
|
110
|
+
}
|
|
111
|
+
state = recoverRecord(state, historyRecordSchema.parse(JSON.parse(source)), context);
|
|
112
|
+
}
|
|
113
|
+
if (context.mode === 'automatic' && paths.length === 0 && state.index.summaries.length === 0) {
|
|
114
|
+
throw historyStateError('Retained records are insufficient for automatic repair.');
|
|
115
|
+
}
|
|
116
|
+
return state;
|
|
117
|
+
}
|
|
118
|
+
async function publishRepair(store, context, state, paths) {
|
|
119
|
+
const available = new Set(paths);
|
|
120
|
+
const index = retainCompactHistory({
|
|
121
|
+
...state.index,
|
|
122
|
+
summaries: state
|
|
123
|
+
.index
|
|
124
|
+
.summaries
|
|
125
|
+
.map(function replayAvailability(summary) {
|
|
126
|
+
return {
|
|
127
|
+
...summary,
|
|
128
|
+
replayable: summary.replayable &&
|
|
129
|
+
available.has(path.join(context.directory, 'runs', `${summary.id}.json`))
|
|
130
|
+
};
|
|
131
|
+
})
|
|
132
|
+
}, context.policy, context.now);
|
|
133
|
+
const validDurations = durationHistoryStateSchema.parse(state.durations);
|
|
134
|
+
const validIndex = compactHistorySchema.parse(index);
|
|
135
|
+
await store.write(durationStatePath(context.directory), JSON.stringify(validDurations));
|
|
136
|
+
await store.write(path.join(context.directory, 'history', 'index.json'), JSON.stringify(validIndex));
|
|
137
|
+
}
|
|
138
|
+
export async function repairHistory(store, context) {
|
|
139
|
+
try {
|
|
140
|
+
return await store.withLock(async function rebuildHistory() {
|
|
141
|
+
const deadline = context.mode === 'automatic'
|
|
142
|
+
? performance.now() + automaticRepairBudgetMilliseconds
|
|
143
|
+
: Number.POSITIVE_INFINITY;
|
|
144
|
+
const listed = await store.list(path.join(context.directory, 'runs'));
|
|
145
|
+
const paths = listed.toSorted(function alphabetical(left, right) {
|
|
146
|
+
return left.localeCompare(right);
|
|
147
|
+
});
|
|
148
|
+
const state = await rebuildRecords(store, context, paths, deadline);
|
|
149
|
+
assertBudget(deadline);
|
|
150
|
+
await publishRepair(store, context, state, paths);
|
|
151
|
+
return { rebuiltRunCount: paths.length, diagnostics: state.diagnostics, dataLoss: state.dataLoss };
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
throw historyStateError(error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=history-repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-repair.js","sourceRoot":"","sources":["../../../../source/run/history-repair.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { historyStateError } from "./history-state-error.js";
|
|
4
|
+
import { historyRecordSchema } from "./history-record.js";
|
|
5
|
+
import { historyRunStatus } from "./history-outcomes.js";
|
|
6
|
+
const millisecondsPerDay = 86_400_000;
|
|
7
|
+
export const manifestSchema = z.object({
|
|
8
|
+
version: z.literal(1),
|
|
9
|
+
id: z.string(),
|
|
10
|
+
startedAt: z.iso.datetime({ offset: true }),
|
|
11
|
+
status: z.enum(['passed', 'failed', 'runner-error', 'interrupted', 'inconclusive'])
|
|
12
|
+
});
|
|
13
|
+
export async function artifactMetadata(store, target, fallback, name) {
|
|
14
|
+
const source = await store.read(path.join(target, 'retention.json'));
|
|
15
|
+
const value = source === null ? fallback : JSON.parse(source);
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
throw new Error(`Missing artifact retention metadata: ${target}`);
|
|
18
|
+
}
|
|
19
|
+
const parsed = manifestSchema.parse(value);
|
|
20
|
+
if (parsed.id !== name) {
|
|
21
|
+
throw new Error(`Artifact identity does not match path: ${target}`);
|
|
22
|
+
}
|
|
23
|
+
return parsed;
|
|
24
|
+
}
|
|
25
|
+
function assertRecordCommitted(record, input) {
|
|
26
|
+
if (record.status !== 'completed') {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const cutoff = Date.parse(input.now) - input.policy.staleIdentityRetentionDays * millisecondsPerDay;
|
|
30
|
+
if (Date.parse(record.startedAt) < cutoff) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const receipt = input.index.receipts.find(function (value) {
|
|
34
|
+
return value.id === record.id;
|
|
35
|
+
});
|
|
36
|
+
if (receipt?.state !== 'completed') {
|
|
37
|
+
throw historyStateError(`Run ${record.id} has an incomplete history commit.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function recordMetadata(input, recordPath) {
|
|
41
|
+
const { store } = input;
|
|
42
|
+
const record = historyRecordSchema.parse(JSON.parse(await store.read(recordPath) ?? 'null'));
|
|
43
|
+
if (path.basename(recordPath) !== `${record.id}.json`) {
|
|
44
|
+
throw new Error(`Record identity does not match path: ${recordPath}`);
|
|
45
|
+
}
|
|
46
|
+
assertRecordCommitted(record, input);
|
|
47
|
+
return manifestSchema.parse({
|
|
48
|
+
version: 1,
|
|
49
|
+
id: record.id,
|
|
50
|
+
startedAt: record.startedAt,
|
|
51
|
+
status: historyRunStatus(record)
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=history-retention-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-retention-metadata.js","sourceRoot":"","sources":["../../../../source/run/history-retention-metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { lstat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { checkHistoryMaintenanceBudget } from "./history-maintenance-budget.js";
|
|
4
|
+
import { historyDirectoryNames, compareHistoryRuns, assertHistoryRunId } from "./history-state-access.js";
|
|
5
|
+
import { manifestSchema, recordMetadata, artifactMetadata } from "./history-retention-metadata.js";
|
|
6
|
+
const millisecondsPerDay = 86_400_000;
|
|
7
|
+
async function readRecords(input, records, retain) {
|
|
8
|
+
for (const recordPath of records) {
|
|
9
|
+
checkHistoryMaintenanceBudget();
|
|
10
|
+
const record = await recordMetadata(input, recordPath);
|
|
11
|
+
retain(record.id, record);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function artifactDirectory(input, metadata, retain, name) {
|
|
15
|
+
const target = path.join(input.runs, name);
|
|
16
|
+
const status = await lstat(target);
|
|
17
|
+
if (!status.isDirectory()) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const parsed = await artifactMetadata(input.store, target, metadata.get(name), name);
|
|
21
|
+
if (!metadata.has(name)) {
|
|
22
|
+
retain(name, parsed);
|
|
23
|
+
}
|
|
24
|
+
return target;
|
|
25
|
+
}
|
|
26
|
+
async function readArtifacts(input, metadata, retain) {
|
|
27
|
+
const names = await historyDirectoryNames(input.runs);
|
|
28
|
+
const directories = [];
|
|
29
|
+
for (const name of names) {
|
|
30
|
+
checkHistoryMaintenanceBudget();
|
|
31
|
+
directories.push(await artifactDirectory(input, metadata, retain, name));
|
|
32
|
+
}
|
|
33
|
+
return directories.filter(function existingDirectory(directory) {
|
|
34
|
+
return directory !== null;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export async function readRetentionCatalog(input) {
|
|
38
|
+
const metadata = new Map(input.index.summaries.map(function retainedSummary(summary) {
|
|
39
|
+
assertHistoryRunId(summary.id);
|
|
40
|
+
return [summary.id, manifestSchema.parse({ version: 1, ...summary })];
|
|
41
|
+
}));
|
|
42
|
+
function retainRunMetadata(key, value) {
|
|
43
|
+
metadata.set(key, value);
|
|
44
|
+
}
|
|
45
|
+
const records = await input.store.list(input.runs);
|
|
46
|
+
await readRecords(input, records, retainRunMetadata);
|
|
47
|
+
const artifactDirectories = await readArtifacts(input, metadata, retainRunMetadata);
|
|
48
|
+
return { metadata, records, artifactDirectories };
|
|
49
|
+
}
|
|
50
|
+
export function selectHistoryRemovals(catalog, runs, policy, now) {
|
|
51
|
+
checkHistoryMaintenanceBudget();
|
|
52
|
+
const { metadata, records, artifactDirectories } = catalog;
|
|
53
|
+
const ordered = Array.from(metadata.values()).toSorted(compareHistoryRuns);
|
|
54
|
+
const retainedRecords = new Set(ordered
|
|
55
|
+
.filter(function (value) {
|
|
56
|
+
return records.includes(path.join(runs, `${value.id}.json`));
|
|
57
|
+
})
|
|
58
|
+
.slice(0, policy.detailedRunLimit)
|
|
59
|
+
.map(function (value) {
|
|
60
|
+
return value.id;
|
|
61
|
+
}));
|
|
62
|
+
const successful = new Set(ordered
|
|
63
|
+
.filter(function (value) {
|
|
64
|
+
return value.status === 'passed';
|
|
65
|
+
})
|
|
66
|
+
.slice(0, policy.successfulArtifactRunLimit)
|
|
67
|
+
.map(function (value) {
|
|
68
|
+
return value.id;
|
|
69
|
+
}));
|
|
70
|
+
const removedRecords = records.filter(function (value) {
|
|
71
|
+
return !retainedRecords.has(path.basename(value, '.json'));
|
|
72
|
+
});
|
|
73
|
+
const removedArtifacts = artifactDirectories.filter(function expired(target) {
|
|
74
|
+
const value = metadata.get(path.basename(target));
|
|
75
|
+
if (value === undefined) {
|
|
76
|
+
throw new Error(`Missing metadata: ${target}`);
|
|
77
|
+
}
|
|
78
|
+
return value.status === 'passed'
|
|
79
|
+
? !successful.has(value.id)
|
|
80
|
+
: Date.parse(value.startedAt) <
|
|
81
|
+
Date.parse(now) - policy.failingArtifactRetentionDays * millisecondsPerDay;
|
|
82
|
+
});
|
|
83
|
+
return { retainedRecords, removedRecords, removedArtifacts, successfulRuns: successful };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=history-retention-records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-retention-records.js","sourceRoot":"","sources":["../../../../source/run/history-retention-records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { readdir, lstat, realpath, rm } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { hostname } from 'node:os';
|
|
4
|
+
import lockfile from 'proper-lockfile';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { checkHistoryMaintenanceBudget, historyMaintenanceDiagnostics, historyMaintenanceDeadline, HistoryMaintenanceDeferredError } from "./history-maintenance-budget.js";
|
|
7
|
+
import { RunCollectionError } from "./run-errors.js";
|
|
8
|
+
import { createNodeHistoryStorage } from "./node-history-storage.js";
|
|
9
|
+
function ownerAlive(pid) {
|
|
10
|
+
try {
|
|
11
|
+
process.kill(pid, 0);
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
if (error instanceof Error && Reflect.get(error, 'code') === 'ESRCH') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function rejectActiveOwner(message) {
|
|
22
|
+
if (Number.isFinite(historyMaintenanceDeadline())) {
|
|
23
|
+
throw new HistoryMaintenanceDeferredError();
|
|
24
|
+
}
|
|
25
|
+
throw new Error(message);
|
|
26
|
+
}
|
|
27
|
+
async function assertOwnerInactive(store, ownerPath, options) {
|
|
28
|
+
const owner = z
|
|
29
|
+
.object({ pid: z.number().int().positive(), host: z.string() })
|
|
30
|
+
.parse(JSON.parse(await store.read(ownerPath) ?? 'null'));
|
|
31
|
+
if (owner.host !== hostname()) {
|
|
32
|
+
const live = await lockfile.check(ownerPath, {
|
|
33
|
+
lockfilePath: `${ownerPath}.lease`,
|
|
34
|
+
stale: options.config.history.staleLockMilliseconds
|
|
35
|
+
});
|
|
36
|
+
if (live) {
|
|
37
|
+
rejectActiveOwner('History is owned by a run on another host.');
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (ownerAlive(owner.pid)) {
|
|
42
|
+
rejectActiveOwner('Persisted runs are active. Finish them before history maintenance.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function existingStatus(target) {
|
|
46
|
+
checkHistoryMaintenanceBudget();
|
|
47
|
+
try {
|
|
48
|
+
return await lstat(target);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
if (error instanceof Error && Reflect.get(error, 'code') === 'ENOENT') {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export async function detailedRecordState(filePath) {
|
|
58
|
+
const status = await existingStatus(filePath);
|
|
59
|
+
if (status === null) {
|
|
60
|
+
return 'pruned';
|
|
61
|
+
}
|
|
62
|
+
return status.isFile() ? 'available' : 'unavailable';
|
|
63
|
+
}
|
|
64
|
+
async function assertNotLinked(target) {
|
|
65
|
+
const status = await existingStatus(target);
|
|
66
|
+
if (status?.isSymbolicLink() === true) {
|
|
67
|
+
throw new Error(`History directory is a symbolic link: ${target}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export async function historyDirectoryNames(directory) {
|
|
71
|
+
checkHistoryMaintenanceBudget();
|
|
72
|
+
try {
|
|
73
|
+
return await readdir(directory);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error instanceof Error && Reflect.get(error, 'code') === 'ENOENT') {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function containsProject(directory, projectRoot) {
|
|
83
|
+
const relative = path.relative(directory, projectRoot);
|
|
84
|
+
return relative === '' ||
|
|
85
|
+
relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
86
|
+
}
|
|
87
|
+
export function createHistoryAccess(options) {
|
|
88
|
+
const directory = path.resolve(options.projectRoot, options.config.runtimeStateDir);
|
|
89
|
+
const policy = options.config.history;
|
|
90
|
+
const store = createNodeHistoryStorage(directory, policy);
|
|
91
|
+
const runs = path.join(directory, 'runs');
|
|
92
|
+
const abandonedOwners = new Set();
|
|
93
|
+
async function guarded(operation) {
|
|
94
|
+
try {
|
|
95
|
+
return await store.withLock(operation);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (error instanceof RunCollectionError || error instanceof HistoryMaintenanceDeferredError) {
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
throw new RunCollectionError(`History operation failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error }, 'runtime-state');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function assertIdle() {
|
|
105
|
+
abandonedOwners.clear();
|
|
106
|
+
const listed = await historyDirectoryNames(path.join(directory, 'active-runs'));
|
|
107
|
+
const names = listed.filter(function ownerMetadata(name) {
|
|
108
|
+
return name.endsWith('.json');
|
|
109
|
+
});
|
|
110
|
+
for (const name of names) {
|
|
111
|
+
checkHistoryMaintenanceBudget();
|
|
112
|
+
await assertOwnerInactive(store, path.join(directory, 'active-runs', name), options);
|
|
113
|
+
abandonedOwners.add(name);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function assertOwnedLocation() {
|
|
117
|
+
for (const name of ['runs', 'history', 'duration-history', 'active-runs']) {
|
|
118
|
+
const target = path.join(directory, name);
|
|
119
|
+
await assertNotLinked(target);
|
|
120
|
+
}
|
|
121
|
+
const resolved = await realpath(directory);
|
|
122
|
+
if (resolved === path.parse(resolved).root || containsProject(resolved, await realpath(options.projectRoot))) {
|
|
123
|
+
throw new Error('History state must have its own directory.');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
directory,
|
|
128
|
+
policy,
|
|
129
|
+
store,
|
|
130
|
+
runs,
|
|
131
|
+
guarded,
|
|
132
|
+
assertIdle,
|
|
133
|
+
async removeAbandonedOwners() {
|
|
134
|
+
for (const name of abandonedOwners) {
|
|
135
|
+
checkHistoryMaintenanceBudget();
|
|
136
|
+
const ownerPath = path.join(directory, 'active-runs', name);
|
|
137
|
+
await rm(`${ownerPath}.lease`, { recursive: true, force: true });
|
|
138
|
+
await rm(ownerPath, { force: true });
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
assertOwnedLocation,
|
|
142
|
+
diagnostics() {
|
|
143
|
+
return [
|
|
144
|
+
...historyMaintenanceDiagnostics(),
|
|
145
|
+
...Array.from(abandonedOwners, function (name) {
|
|
146
|
+
return `Abandoned run ownership: ${name}`;
|
|
147
|
+
})
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export function assertHistoryRunId(id) {
|
|
153
|
+
if (id === '' || path.basename(id) !== id || id === '..' || id === '.') {
|
|
154
|
+
throw new Error('Invalid history run identity.');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export function compareHistoryRuns(left, right) {
|
|
158
|
+
const time = Date.parse(right.startedAt) - Date.parse(left.startedAt);
|
|
159
|
+
return time === 0 ? left.id.localeCompare(right.id) : time;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=history-state-access.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-state-access.js","sourceRoot":"","sources":["../../../../source/run/history-state-access.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { RunCollectionError } from "./run-errors.js";
|
|
2
|
+
export function historyStateError(cause) {
|
|
3
|
+
if (cause instanceof RunCollectionError) {
|
|
4
|
+
return cause;
|
|
5
|
+
}
|
|
6
|
+
return new RunCollectionError('History state is unavailable. Run overkill history compact to repair it.', { cause }, 'runtime-state');
|
|
7
|
+
}
|
|
8
|
+
export class UnsupportedHistoryVersionError extends RunCollectionError {
|
|
9
|
+
constructor(version, options) {
|
|
10
|
+
super(`Unsupported history schema version ${version}. Use a compatible Overkill version.`, options, 'runtime-state');
|
|
11
|
+
this.name = 'UnsupportedHistoryVersionError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function parsedSchemaVersion(value) {
|
|
15
|
+
if (typeof value !== 'object' || value === null) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const version = Reflect.get(value, 'version');
|
|
19
|
+
return typeof version === 'number' ? version : null;
|
|
20
|
+
}
|
|
21
|
+
export function historySchemaVersion(source) {
|
|
22
|
+
try {
|
|
23
|
+
return parsedSchemaVersion(JSON.parse(source));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function assertSupportedHistoryVersion(source, maximum) {
|
|
30
|
+
const version = historySchemaVersion(source);
|
|
31
|
+
if (version !== null && version > maximum) {
|
|
32
|
+
throw new UnsupportedHistoryVersionError(version, { cause: null });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=history-state-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-state-error.js","sourceRoot":"","sources":["../../../../source/run/history-state-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,kBAAkB,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,kBAAkB,CACzB,0EAA0E,EAC1E,EAAE,KAAK,EAAE,EACT,eAAe,CAClB,CAAC;AACN,CAAC;AAED,MAAM,OAAO,8BAA+B,SAAQ,kBAAkB;IAClE,YAAmB,OAAe,EAAE,OAA+B;QAC/D,KAAK,CACD,sCAAsC,OAAO,sCAAsC,EACnF,OAAO,EACP,eAAe,CAClB,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,gCAAgC,CAAC;IACjD,CAAC;CACJ;AAED,SAAS,mBAAmB,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,GAAY,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACvD,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAc;IAC/C,IAAI,CAAC;QACD,OAAO,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,MAAc,EAAE,OAAe;IACzE,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;QACxC,MAAM,IAAI,8BAA8B,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HistoryPolicy } from '../config/history-policy.ts';
|
|
2
|
+
import type { HistoryOptions } from './history-types.ts';
|
|
3
|
+
export type HistoryMaintenance = (options: HistoryOptions) => Promise<readonly string[]>;
|
|
4
|
+
export type HistoryStorage = {
|
|
5
|
+
readonly beginRun: (id: string) => Promise<() => Promise<void>>;
|
|
6
|
+
readonly list: (directory: string) => Promise<readonly string[]>;
|
|
7
|
+
readonly read: (filePath: string) => Promise<string | null>;
|
|
8
|
+
readonly write: (filePath: string, content: string) => Promise<void>;
|
|
9
|
+
readonly withLock: <T>(operation: () => Promise<T>) => Promise<T>;
|
|
10
|
+
};
|
|
11
|
+
export type RuntimeStateStore = Pick<HistoryStorage, 'read' | 'write'>;
|
|
12
|
+
export type HistoryStorageFactory = (directory: string, policy: HistoryPolicy) => HistoryStorage;
|
|
13
|
+
//# sourceMappingURL=history-storage-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-storage-types.d.ts","sourceRoot":"","sources":["../../../../source/run/history-storage-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;AAEzF,MAAM,MAAM,cAAc,GAAG;IACzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IACjE,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACrE,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AACvE,MAAM,MAAM,qBAAqB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,KAAK,cAAc,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { repairHistory } from "./history-repair.js";
|
|
3
|
+
import { recordDurationContributions } from "./history-outcomes.js";
|
|
4
|
+
import { durationHistoryStateSchema, durationStatePath, emptyDurationState, ingestDurationState, readDurationState } from "./duration-history-storage.js";
|
|
5
|
+
import { emptyCompactHistory, ingestCompactRecord } from "./compact-history.js";
|
|
6
|
+
import { compactHistorySchema } from "./compact-history-schema.js";
|
|
7
|
+
import { historyStateError, historySchemaVersion, assertSupportedHistoryVersion } from "./history-state-error.js";
|
|
8
|
+
async function parsedCompactHistory(store, directory) {
|
|
9
|
+
const content = await store.read(path.join(directory, 'history', 'index.json'));
|
|
10
|
+
if (content === null) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
assertSupportedHistoryVersion(content, 1);
|
|
14
|
+
return compactHistorySchema.parse(JSON.parse(content));
|
|
15
|
+
}
|
|
16
|
+
export async function readCompactHistory(store, directory) {
|
|
17
|
+
try {
|
|
18
|
+
return await parsedCompactHistory(store, directory);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw historyStateError(error);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function updateCompactHistory(store, record, context) {
|
|
25
|
+
const { directory, policy, now, testFamily } = context;
|
|
26
|
+
const source = await store.read(path.join(directory, 'history', 'index.json'));
|
|
27
|
+
if (source !== null && historySchemaVersion(source) === 0) {
|
|
28
|
+
const retained = {
|
|
29
|
+
...store,
|
|
30
|
+
async list(recordDirectory) {
|
|
31
|
+
const files = await store.list(recordDirectory);
|
|
32
|
+
return files.filter(function previousRun(filePath) {
|
|
33
|
+
return path.basename(filePath) !== `${record.id}.json`;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
await repairHistory(retained, { directory, policy, now, mode: 'automatic' });
|
|
38
|
+
}
|
|
39
|
+
await store.withLock(async function commitHistory() {
|
|
40
|
+
const current = await readCompactHistory(store, directory) ?? emptyCompactHistory(now);
|
|
41
|
+
if (record.status === 'completed') {
|
|
42
|
+
const state = await readDurationState(store, directory, now) ?? emptyDurationState(now);
|
|
43
|
+
const nextDurations = ingestDurationState(state, recordDurationContributions(record), {
|
|
44
|
+
run: { id: record.id, startedAt: record.startedAt },
|
|
45
|
+
source: 'run',
|
|
46
|
+
policy,
|
|
47
|
+
now
|
|
48
|
+
});
|
|
49
|
+
await store.write(durationStatePath(directory), JSON.stringify(durationHistoryStateSchema.parse(nextDurations)));
|
|
50
|
+
}
|
|
51
|
+
const next = ingestCompactRecord(current, record, { policy, now, testFamily });
|
|
52
|
+
await store.write(path.join(directory, 'history', 'index.json'), `${JSON.stringify(compactHistorySchema.parse(next))}\n`);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=history-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-storage.js","sourceRoot":"","sources":["../../../../source/run/history-storage.ts"],"names":[],"mappings":"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"}
|