@amalgm/shell 0.1.135 → 0.1.137
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/bounded-for-each.d.ts +3 -0
- package/dist/bounded-for-each.js +26 -0
- package/dist/bounded-for-each.js.map +1 -0
- package/dist/filesystem.d.ts +3 -0
- package/dist/filesystem.js +11 -0
- package/dist/filesystem.js.map +1 -1
- package/dist/transfer-instrumentation.d.ts +18 -0
- package/dist/transfer-instrumentation.js +70 -0
- package/dist/transfer-instrumentation.js.map +1 -1
- package/dist/user-ground-host.js +50 -30
- package/dist/user-ground-host.js.map +1 -1
- package/dist/workspace-add-staging.d.ts +98 -34
- package/dist/workspace-add-staging.js +255 -149
- package/dist/workspace-add-staging.js.map +1 -1
- package/npm-shrinkwrap.json +6 -6
- package/package.json +2 -2
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Run `perform` over every item with at most `concurrency` in flight. The
|
|
2
|
+
* first failure stops admission and rejects the whole loop. */
|
|
3
|
+
export declare function boundedForEach<T>(items: readonly T[], concurrency: number, perform: (item: T) => Promise<void>): Promise<void>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Run `perform` over every item with at most `concurrency` in flight. The
|
|
2
|
+
* first failure stops admission and rejects the whole loop. */
|
|
3
|
+
export async function boundedForEach(items, concurrency, perform) {
|
|
4
|
+
if (!Number.isSafeInteger(concurrency) || concurrency < 1) {
|
|
5
|
+
throw new Error("bounded loop concurrency must be a positive integer");
|
|
6
|
+
}
|
|
7
|
+
let next = 0;
|
|
8
|
+
let stopped = false;
|
|
9
|
+
const worker = async () => {
|
|
10
|
+
while (!stopped) {
|
|
11
|
+
const index = next;
|
|
12
|
+
next += 1;
|
|
13
|
+
if (index >= items.length)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
await perform(items[index]);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
stopped = true;
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=bounded-for-each.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-for-each.js","sourceRoot":"","sources":["../src/bounded-for-each.ts"],"names":[],"mappings":"AAAA;+DAC+D;AAC/D,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAmB,EACnB,WAAmB,EACnB,OAAmC;IAEnC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,MAAM,GAAG,KAAK,IAAI,EAAE;QACxB,OAAO,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC;YACnB,IAAI,IAAI,CAAC,CAAC;YACV,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO;YAClC,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC,CAAC;YACnC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAC1B,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAC/C,GAAG,EAAE,CAAC,MAAM,EAAE,CACf,CAAC,CAAC;AACL,CAAC"}
|
package/dist/filesystem.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export declare function ensurePrivateDir(directory: string): void;
|
|
|
3
3
|
* gets 0755 — the same default a fresh mkdir gives the user — and an
|
|
4
4
|
* existing directory keeps whatever mode the user chose. */
|
|
5
5
|
export declare function ensureUserDir(directory: string): void;
|
|
6
|
+
/** The batch form of ensureUserDir: the same mode law for a whole directory
|
|
7
|
+
* skeleton, created ahead of the files it will hold and off the event loop. */
|
|
8
|
+
export declare function ensureUserDirs(directories: readonly string[], concurrency: number): Promise<void>;
|
|
6
9
|
export declare function atomicWrite(file: string, bytes: string | Uint8Array, mode?: number): void;
|
|
7
10
|
export declare function atomicCopy(source: string, destination: string, mode?: number): void;
|
|
8
11
|
/** Assemble verified chunk files without holding the complete artifact in RAM. */
|
package/dist/filesystem.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { constants, chmodSync, copyFileSync, createReadStream, createWriteStream, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { chmod, mkdir } from "node:fs/promises";
|
|
3
4
|
import { dirname } from "node:path";
|
|
4
5
|
import { once } from "node:events";
|
|
6
|
+
import { boundedForEach } from "./bounded-for-each.js";
|
|
5
7
|
export function ensurePrivateDir(directory) {
|
|
6
8
|
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
7
9
|
chmodSync(directory, 0o700);
|
|
@@ -14,6 +16,15 @@ export function ensureUserDir(directory) {
|
|
|
14
16
|
chmodSync(directory, 0o755);
|
|
15
17
|
}
|
|
16
18
|
}
|
|
19
|
+
/** The batch form of ensureUserDir: the same mode law for a whole directory
|
|
20
|
+
* skeleton, created ahead of the files it will hold and off the event loop. */
|
|
21
|
+
export async function ensureUserDirs(directories, concurrency) {
|
|
22
|
+
await boundedForEach(directories, concurrency, async (directory) => {
|
|
23
|
+
if (await mkdir(directory, { recursive: true, mode: 0o755 }) !== undefined) {
|
|
24
|
+
await chmod(directory, 0o755);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
17
28
|
/** File helpers own the file, never the parent's mode: an absent parent is
|
|
18
29
|
* created private, an existing one — private or user-visible — keeps its
|
|
19
30
|
* mode. */
|
package/dist/filesystem.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,3 +26,21 @@ export declare class TransferLegs {
|
|
|
26
26
|
private enter;
|
|
27
27
|
private exit;
|
|
28
28
|
}
|
|
29
|
+
/** Partition one concurrent phase by three named activities. Counts preserve
|
|
30
|
+
* a bit until the last operation of that kind settles; the eight reported
|
|
31
|
+
* states therefore sum to wall time instead of double-counting overlap. */
|
|
32
|
+
export declare class ConcurrentActivityClock<Activity extends string> {
|
|
33
|
+
private readonly activities;
|
|
34
|
+
private readonly counts;
|
|
35
|
+
private readonly totals;
|
|
36
|
+
private state;
|
|
37
|
+
private changedAt;
|
|
38
|
+
constructor(activities: readonly [Activity, Activity, Activity]);
|
|
39
|
+
time<T>(activity: Activity, work: () => Promise<T>): Promise<T>;
|
|
40
|
+
timeSync<T>(activity: Activity, work: () => T): T;
|
|
41
|
+
/** Prefix + active activity names form stable ledger keys. */
|
|
42
|
+
report(prefix: string): Record<string, number>;
|
|
43
|
+
private index;
|
|
44
|
+
private transition;
|
|
45
|
+
private record;
|
|
46
|
+
}
|
|
@@ -65,4 +65,74 @@ export class TransferLegs {
|
|
|
65
65
|
this.quietSince = now;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
/** Partition one concurrent phase by three named activities. Counts preserve
|
|
69
|
+
* a bit until the last operation of that kind settles; the eight reported
|
|
70
|
+
* states therefore sum to wall time instead of double-counting overlap. */
|
|
71
|
+
export class ConcurrentActivityClock {
|
|
72
|
+
activities;
|
|
73
|
+
counts = [0, 0, 0];
|
|
74
|
+
totals = Array.from({ length: 8 }, () => 0);
|
|
75
|
+
state = 0;
|
|
76
|
+
changedAt = performance.now();
|
|
77
|
+
constructor(activities) {
|
|
78
|
+
this.activities = activities;
|
|
79
|
+
if (activities.some((activity) => activity.length === 0)
|
|
80
|
+
|| new Set(activities).size !== activities.length) {
|
|
81
|
+
throw new Error("concurrent activity names must be distinct");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async time(activity, work) {
|
|
85
|
+
const index = this.index(activity);
|
|
86
|
+
this.transition(index, 1);
|
|
87
|
+
try {
|
|
88
|
+
return await work();
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
this.transition(index, -1);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
timeSync(activity, work) {
|
|
95
|
+
const index = this.index(activity);
|
|
96
|
+
this.transition(index, 1);
|
|
97
|
+
try {
|
|
98
|
+
return work();
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
this.transition(index, -1);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Prefix + active activity names form stable ledger keys. */
|
|
105
|
+
report(prefix) {
|
|
106
|
+
if (!prefix)
|
|
107
|
+
throw new Error("concurrent activity report needs a prefix");
|
|
108
|
+
this.record(performance.now());
|
|
109
|
+
const key = (state) => {
|
|
110
|
+
if (state === 0)
|
|
111
|
+
return `${prefix}NeitherMs`;
|
|
112
|
+
const names = this.activities.filter((_activity, index) => (state & (1 << index)) !== 0);
|
|
113
|
+
const suffix = names.length === 1 ? "Only" : "";
|
|
114
|
+
return `${prefix}${names.map((name) => name.charAt(0).toUpperCase() + name.slice(1)).join("")}${suffix}Ms`;
|
|
115
|
+
};
|
|
116
|
+
return Object.fromEntries(this.totals.map((duration, state) => [key(state), Math.round(duration)]));
|
|
117
|
+
}
|
|
118
|
+
index(activity) {
|
|
119
|
+
const index = this.activities.indexOf(activity);
|
|
120
|
+
if (index < 0)
|
|
121
|
+
throw new Error(`unknown concurrent activity ${activity}`);
|
|
122
|
+
return index;
|
|
123
|
+
}
|
|
124
|
+
transition(index, delta) {
|
|
125
|
+
const now = performance.now();
|
|
126
|
+
this.record(now);
|
|
127
|
+
const next = (this.counts[index] ?? 0) + delta;
|
|
128
|
+
if (next < 0)
|
|
129
|
+
throw new Error("concurrent activity clock lost an operation");
|
|
130
|
+
this.counts[index] = next;
|
|
131
|
+
this.state = this.counts.reduce((mask, count, bit) => count > 0 ? mask | (1 << bit) : mask, 0);
|
|
132
|
+
}
|
|
133
|
+
record(now) {
|
|
134
|
+
this.totals[this.state] = (this.totals[this.state] ?? 0) + (now - this.changedAt);
|
|
135
|
+
this.changedAt = now;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
68
138
|
//# sourceMappingURL=transfer-instrumentation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-instrumentation.js","sourceRoot":"","sources":["../src/transfer-instrumentation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,YAAY;IACN,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,QAAQ,GAAG,CAAC,CAAC;IACb,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAC/B,MAAM,GAAG,CAAC,CAAC;IAEnB;2EACuE;IACvE,GAAG,CAAC,GAAW,EAAE,EAAU;QACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;YAAE,OAAO;QAC5C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,IAAsB;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,QAAQ,CAAI,GAAW,EAAE,IAAa;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;yCACqC;IACrC,MAAM;QACJ,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,OAAO;YACL,GAAG,MAAM,CAAC,WAAW,CACnB,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAC3D;YACD,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;SAC/C,CAAC;IACJ,CAAC;IAEO,KAAK;QACX,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,IAAI,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC;QAC9D,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,IAAI,CAAC,GAAW,EAAE,SAAiB;QACzC,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAAC,CAAC;QAC/B,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;YAAE,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;IACjD,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"transfer-instrumentation.js","sourceRoot":"","sources":["../src/transfer-instrumentation.ts"],"names":[],"mappings":"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"}
|
package/dist/user-ground-host.js
CHANGED
|
@@ -14,6 +14,7 @@ import { indexRowsByOutermostRoot } from "./ground-root-index.js";
|
|
|
14
14
|
import { ContentCacheDownloadSet, captureContentFile, contentBlockCollector, hasSealedContent, hashContentFile, pruneSettledContentCache, sealCapturedArtifact, } from "./content-cache-host.js";
|
|
15
15
|
import { RegisterUploadFusion } from "./register-upload-fusion.js";
|
|
16
16
|
import { StagedContentSet, addStagingEvidenceDir, clearAddStagingEvidence, } from "./workspace-add-staging.js";
|
|
17
|
+
import { boundedForEach } from "./bounded-for-each.js";
|
|
17
18
|
import { DirectContentPlane } from "./content-direct.js";
|
|
18
19
|
import { encodeContentWireBytes } from "./content-wire-codec.js";
|
|
19
20
|
import { TransferLegs } from "./transfer-instrumentation.js";
|
|
@@ -43,6 +44,12 @@ const CARGO_SEGMENT_LOAD_CONCURRENCY = 8;
|
|
|
43
44
|
* few broad ranged reads. Memory is bounded by the byte laws below, never by
|
|
44
45
|
* this count. */
|
|
45
46
|
const DIRECT_OBJECT_DOWNLOAD_CONCURRENCY = CONTENT_REFS_BATCH_OBJECTS;
|
|
47
|
+
/** Independent destination writers. Pack reads are intentionally few, but
|
|
48
|
+
* one pack may contain thousands of unrelated files; those files must not
|
|
49
|
+
* inherit the pack's request count as their filesystem concurrency. Sixteen
|
|
50
|
+
* handles are bounded on a 1 GiB runtime and enough to hide metadata latency
|
|
51
|
+
* behind the volume's byte throughput. */
|
|
52
|
+
const DIRECT_CONTENT_STORE_CONCURRENCY = 16;
|
|
46
53
|
// Opening one protected object transiently retains the fetched envelope,
|
|
47
54
|
// WebCrypto's ciphertext-with-tag input, and the plaintext. Bound plaintext
|
|
48
55
|
// to two full blocks so those three representations stay below 96 MiB even
|
|
@@ -400,7 +407,7 @@ export class UserGroundHost {
|
|
|
400
407
|
});
|
|
401
408
|
}
|
|
402
409
|
},
|
|
403
|
-
onStage: async (stage) => {
|
|
410
|
+
onStage: async (stage, measurements) => {
|
|
404
411
|
const now = performance.now();
|
|
405
412
|
this.stage({
|
|
406
413
|
primitive: stage === "watching" ? "watch" : "download",
|
|
@@ -408,6 +415,7 @@ export class UserGroundHost {
|
|
|
408
415
|
status: "completed",
|
|
409
416
|
workspaceId: input.workspace.uuid,
|
|
410
417
|
durationMs: now - milestoneAt,
|
|
418
|
+
...(measurements ? { measurements } : {}),
|
|
411
419
|
});
|
|
412
420
|
milestoneAt = now;
|
|
413
421
|
await this.options.onWorkspaceAddStage?.({
|
|
@@ -1870,7 +1878,7 @@ export class UserGroundHost {
|
|
|
1870
1878
|
},
|
|
1871
1879
|
});
|
|
1872
1880
|
const downloads = new ContentCacheDownloadSet(cacheDir);
|
|
1873
|
-
|
|
1881
|
+
let stagedSet = null;
|
|
1874
1882
|
const targets = new Map();
|
|
1875
1883
|
const target = (artifact) => {
|
|
1876
1884
|
const found = targets.get(artifact.contentHash);
|
|
@@ -1883,16 +1891,22 @@ export class UserGroundHost {
|
|
|
1883
1891
|
// which stays on the cache rail so a warm re-Add remains a local
|
|
1884
1892
|
// clone instead of a fresh download.
|
|
1885
1893
|
const route = (artifact, manifest) => {
|
|
1886
|
-
const
|
|
1887
|
-
|
|
1894
|
+
const set = stagedSet;
|
|
1895
|
+
const stagedPaths = set && staged?.destinations.get(artifact.contentHash);
|
|
1896
|
+
if (set && stagedPaths && !hasSealedContent(cacheDir, artifact.contentHash, manifest.bytes)) {
|
|
1888
1897
|
stagedArtifacts += 1;
|
|
1889
|
-
targets.set(artifact.contentHash,
|
|
1898
|
+
targets.set(artifact.contentHash, set.target(artifact, manifest, stagedPaths));
|
|
1890
1899
|
}
|
|
1891
1900
|
else {
|
|
1892
1901
|
targets.set(artifact.contentHash, downloads.target(artifact, manifest));
|
|
1893
1902
|
}
|
|
1894
1903
|
};
|
|
1895
1904
|
try {
|
|
1905
|
+
// The staged rail's directory skeleton is the set's first act, so no
|
|
1906
|
+
// chunk's store path includes a mkdir.
|
|
1907
|
+
stagedSet = staged
|
|
1908
|
+
? await StagedContentSet.open(staged.evidenceDir, staged.destinations)
|
|
1909
|
+
: null;
|
|
1896
1910
|
// Every storage object — manifests and blocks alike — is fetched
|
|
1897
1911
|
// straight from content storage over a presigned URL and opened
|
|
1898
1912
|
// locally; the engine plans whole waves against these primitives, so
|
|
@@ -1954,6 +1968,7 @@ export class UserGroundHost {
|
|
|
1954
1968
|
},
|
|
1955
1969
|
}, {
|
|
1956
1970
|
concurrency: DIRECT_OBJECT_DOWNLOAD_CONCURRENCY,
|
|
1971
|
+
storeConcurrency: DIRECT_CONTENT_STORE_CONCURRENCY,
|
|
1957
1972
|
maxInFlightBytes: DIRECT_OBJECT_DOWNLOAD_MAX_IN_FLIGHT_BYTES,
|
|
1958
1973
|
});
|
|
1959
1974
|
const content = new Map();
|
|
@@ -1983,9 +1998,9 @@ export class UserGroundHost {
|
|
|
1983
1998
|
// plan (manifest cache + routing), fetch (storage waits, whose
|
|
1984
1999
|
// decrypt share the plane delta names), hash (chunk verification),
|
|
1985
2000
|
// reuse (retained-chunk re-proof), write (chunk placement), seal
|
|
1986
|
-
// (whole-file proof +
|
|
1987
|
-
// nothing in flight. The staged rail decomposes its own
|
|
1988
|
-
//
|
|
2001
|
+
// (whole-file proof assertion + duplicates), and idle — wall time
|
|
2002
|
+
// with nothing in flight. The staged rail decomposes its own
|
|
2003
|
+
// placement legs below; `stagedArtifacts` counts its placements.
|
|
1989
2004
|
requests,
|
|
1990
2005
|
// The engine's own geometry: how manifests were known (local vs
|
|
1991
2006
|
// fetched, packed vs standalone) and how many planned pack spans
|
|
@@ -5726,9 +5741,11 @@ async function materializeRecords(input) {
|
|
|
5726
5741
|
for (const list of stagedDestinations.values())
|
|
5727
5742
|
list.sort();
|
|
5728
5743
|
}
|
|
5744
|
+
const contentStarted = performance.now();
|
|
5729
5745
|
const fileContent = await readContent([...wanted.values()], staged && stagedDestinations
|
|
5730
5746
|
? { evidenceDir: staged.evidenceDir, destinations: stagedDestinations }
|
|
5731
5747
|
: undefined);
|
|
5748
|
+
const chainStarted = performance.now();
|
|
5732
5749
|
const repositoryChains = new Map();
|
|
5733
5750
|
const walking = repositoryHeads.map(({ record, artifact }) => {
|
|
5734
5751
|
const local = fileContent.get(artifact.contentHash);
|
|
@@ -5773,11 +5790,15 @@ async function materializeRecords(input) {
|
|
|
5773
5790
|
walk.parent = inspectRepositoryTransportFile(parent.file).parentTransportVersion;
|
|
5774
5791
|
}
|
|
5775
5792
|
}
|
|
5793
|
+
const walkStarted = performance.now();
|
|
5794
|
+
let repositoriesMs = 0;
|
|
5776
5795
|
const materializeRepository = async (record, destination) => {
|
|
5777
5796
|
const chain = repositoryChains.get(record.uuid);
|
|
5778
5797
|
if (!chain)
|
|
5779
5798
|
throw new Error(`cloud repository ${record.uuid} transport was not downloaded`);
|
|
5799
|
+
const started = performance.now();
|
|
5780
5800
|
const applied = await applyRepositoryFiles(destination, chain);
|
|
5801
|
+
repositoriesMs += performance.now() - started;
|
|
5781
5802
|
const repository = { record, state: applied };
|
|
5782
5803
|
repositories.push(repository);
|
|
5783
5804
|
repositoriesByUuid.set(record.uuid, repository);
|
|
@@ -5931,6 +5952,7 @@ async function materializeRecords(input) {
|
|
|
5931
5952
|
throw new Error(`materialization for ${record.type} requires its dedicated adapter`);
|
|
5932
5953
|
}
|
|
5933
5954
|
}
|
|
5955
|
+
const rowsStarted = performance.now();
|
|
5934
5956
|
const rows = records.map((record) => {
|
|
5935
5957
|
const relativePath = paths.get(record.uuid);
|
|
5936
5958
|
const absolutePath = relativePath ? join(rootPath, ...relativePath.split("/")) : rootPath;
|
|
@@ -5944,7 +5966,18 @@ async function materializeRecords(input) {
|
|
|
5944
5966
|
...statFingerprint(stats),
|
|
5945
5967
|
};
|
|
5946
5968
|
});
|
|
5947
|
-
|
|
5969
|
+
const finished = performance.now();
|
|
5970
|
+
return {
|
|
5971
|
+
rows,
|
|
5972
|
+
repositories,
|
|
5973
|
+
timing: {
|
|
5974
|
+
contentMs: Math.round(chainStarted - contentStarted),
|
|
5975
|
+
transportChainMs: Math.round(walkStarted - chainStarted),
|
|
5976
|
+
repositoriesMs: Math.round(repositoriesMs),
|
|
5977
|
+
groundWalkMs: Math.round(rowsStarted - walkStarted - repositoriesMs),
|
|
5978
|
+
rowsMs: Math.round(finished - rowsStarted),
|
|
5979
|
+
},
|
|
5980
|
+
};
|
|
5948
5981
|
}
|
|
5949
5982
|
/** Refresh the always-materialized portable reference inventory selected by
|
|
5950
5983
|
* Live. Paths and bindings are local; UUIDs, parents, names, and versions are
|
|
@@ -6193,6 +6226,7 @@ async function installCloudWorkspace(input) {
|
|
|
6193
6226
|
staged: { evidenceDir: addStagingEvidenceDir(database, intent.workspaceId) },
|
|
6194
6227
|
readContent,
|
|
6195
6228
|
});
|
|
6229
|
+
const graphStarted = performance.now();
|
|
6196
6230
|
const rows = projectMaterializedGraph(materialized.rows, materialized.repositories.map((repository) => ({
|
|
6197
6231
|
record: repository.record,
|
|
6198
6232
|
identity: repository.state.identity,
|
|
@@ -6202,7 +6236,13 @@ async function installCloudWorkspace(input) {
|
|
|
6202
6236
|
? join(intent.destinationPath, ...row.relativePath.split("/"))
|
|
6203
6237
|
: intent.destinationPath,
|
|
6204
6238
|
}));
|
|
6205
|
-
|
|
6239
|
+
// The milestone's duration spans the whole materialization; its legs say
|
|
6240
|
+
// where that wall time went after the content set itself.
|
|
6241
|
+
await onStage?.("materialization-verified", {
|
|
6242
|
+
...materialized.timing,
|
|
6243
|
+
graphMs: Math.round(performance.now() - graphStarted),
|
|
6244
|
+
repositories: materialized.repositories.length,
|
|
6245
|
+
});
|
|
6206
6246
|
persistRows(database, identity, intent.resourceId, intent.workspaceId, rows);
|
|
6207
6247
|
input.adoptMaterialization(intent.workspaceId);
|
|
6208
6248
|
await onStage?.("rows-committed");
|
|
@@ -6292,26 +6332,6 @@ async function retryContent(operation, eventualNotFound = false, attempts = 10)
|
|
|
6292
6332
|
}
|
|
6293
6333
|
throw last;
|
|
6294
6334
|
}
|
|
6295
|
-
async function boundedForEach(items, concurrency, perform) {
|
|
6296
|
-
let next = 0;
|
|
6297
|
-
let stopped = false;
|
|
6298
|
-
const worker = async () => {
|
|
6299
|
-
while (!stopped) {
|
|
6300
|
-
const index = next;
|
|
6301
|
-
next += 1;
|
|
6302
|
-
if (index >= items.length)
|
|
6303
|
-
return;
|
|
6304
|
-
try {
|
|
6305
|
-
await perform(items[index]);
|
|
6306
|
-
}
|
|
6307
|
-
catch (error) {
|
|
6308
|
-
stopped = true;
|
|
6309
|
-
throw error;
|
|
6310
|
-
}
|
|
6311
|
-
}
|
|
6312
|
-
};
|
|
6313
|
-
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
|
|
6314
|
-
}
|
|
6315
6335
|
/** Admit queued async tasks with at most `limit` in flight. Scheduling never
|
|
6316
6336
|
* blocks the caller; each task's settlement is its returned promise. The
|
|
6317
6337
|
* admitted task re-checks the bound because a released slot may be claimed
|