源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { spawn } from "node:child_process";
|
||||
import {
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readdirSync,
|
||||
rmSync,
|
||||
writeFileSync
|
||||
} from "node:fs";
|
||||
import { hostname, tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import test from "node:test";
|
||||
import {
|
||||
getElectronCacheLockPath,
|
||||
getElectronCacheRoot,
|
||||
withElectronCacheLock
|
||||
} from "./prewarm-electron.mjs";
|
||||
|
||||
test("resolves Electron's platform cache locations", () => {
|
||||
assert.equal(
|
||||
getElectronCacheRoot({
|
||||
env: {},
|
||||
homeDirectory: "/Users/developer",
|
||||
platform: "darwin"
|
||||
}),
|
||||
"/Users/developer/Library/Caches/electron"
|
||||
);
|
||||
assert.equal(
|
||||
getElectronCacheRoot({
|
||||
env: { XDG_CACHE_HOME: "/cache" },
|
||||
homeDirectory: "/home/developer",
|
||||
platform: "linux"
|
||||
}),
|
||||
"/cache/electron"
|
||||
);
|
||||
assert.equal(
|
||||
getElectronCacheRoot({
|
||||
env: { electron_config_cache: "/custom/electron-cache" },
|
||||
platform: "darwin"
|
||||
}),
|
||||
"/custom/electron-cache"
|
||||
);
|
||||
});
|
||||
|
||||
test("serializes prewarm calls for the same Electron artifact", async () => {
|
||||
const cacheRoot = mkdtempSync(join(tmpdir(), "tutti-electron-cache-"));
|
||||
const lockInput = {
|
||||
arch: "arm64",
|
||||
cacheRoot,
|
||||
electronVersion: "43.2.0",
|
||||
platform: "darwin",
|
||||
pollIntervalMilliseconds: 1
|
||||
};
|
||||
let releaseFirstOperation;
|
||||
let secondOperationStarted = false;
|
||||
let signalFirstOperation;
|
||||
const firstOperationStarted = new Promise((resolvePromise) => {
|
||||
signalFirstOperation = resolvePromise;
|
||||
});
|
||||
|
||||
try {
|
||||
const first = withElectronCacheLock(lockInput, async () => {
|
||||
signalFirstOperation();
|
||||
await new Promise((resolvePromise) => {
|
||||
releaseFirstOperation = resolvePromise;
|
||||
});
|
||||
});
|
||||
await firstOperationStarted;
|
||||
|
||||
const second = withElectronCacheLock(lockInput, async () => {
|
||||
secondOperationStarted = true;
|
||||
});
|
||||
await new Promise((resolvePromise) => setTimeout(resolvePromise, 20));
|
||||
assert.equal(secondOperationStarted, false);
|
||||
|
||||
releaseFirstOperation();
|
||||
await Promise.all([first, second]);
|
||||
assert.equal(secondOperationStarted, true);
|
||||
} finally {
|
||||
rmSync(cacheRoot, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("reclaims a prewarm lock left by a dead local process", async () => {
|
||||
const cacheRoot = mkdtempSync(join(tmpdir(), "tutti-electron-cache-"));
|
||||
const lockInput = {
|
||||
arch: "arm64",
|
||||
cacheRoot,
|
||||
electronVersion: "43.2.0",
|
||||
platform: "darwin",
|
||||
pollIntervalMilliseconds: 1
|
||||
};
|
||||
const lockPath = getElectronCacheLockPath(lockInput);
|
||||
mkdirSync(cacheRoot, { recursive: true });
|
||||
writeFileSync(
|
||||
lockPath,
|
||||
`${JSON.stringify({ hostName: hostname(), processId: 99_999_999 })}\n`
|
||||
);
|
||||
|
||||
try {
|
||||
const result = await withElectronCacheLock(lockInput, () => "ready");
|
||||
assert.equal(result, "ready");
|
||||
} finally {
|
||||
rmSync(cacheRoot, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("serializes concurrent recovery of a stale prewarm lock", async () => {
|
||||
const cacheRoot = mkdtempSync(join(tmpdir(), "tutti-electron-cache-"));
|
||||
const readyDirectory = join(cacheRoot, "ready");
|
||||
const startPath = join(cacheRoot, "start");
|
||||
const activePath = join(cacheRoot, "active");
|
||||
const lockInput = {
|
||||
arch: "arm64",
|
||||
cacheRoot,
|
||||
electronVersion: "43.2.0",
|
||||
platform: "darwin",
|
||||
pollIntervalMilliseconds: 1
|
||||
};
|
||||
const lockPath = getElectronCacheLockPath(lockInput);
|
||||
|
||||
mkdirSync(cacheRoot, { recursive: true });
|
||||
mkdirSync(readyDirectory, { recursive: true });
|
||||
writeFileSync(
|
||||
lockPath,
|
||||
`${JSON.stringify({ hostName: hostname(), processId: 99_999_999 })}\n`
|
||||
);
|
||||
|
||||
try {
|
||||
const children = Array.from({ length: 4 }, () =>
|
||||
spawn(process.execPath, ["--input-type=module", "--eval", childScript], {
|
||||
env: {
|
||||
...process.env,
|
||||
TUTTI_ELECTRON_LOCK_ACTIVE_PATH: activePath,
|
||||
TUTTI_ELECTRON_LOCK_INPUT: JSON.stringify(lockInput),
|
||||
TUTTI_ELECTRON_LOCK_MODULE_URL: new URL(
|
||||
"./prewarm-electron.mjs",
|
||||
import.meta.url
|
||||
).href,
|
||||
TUTTI_ELECTRON_LOCK_READY_DIRECTORY: readyDirectory,
|
||||
TUTTI_ELECTRON_LOCK_START_PATH: startPath
|
||||
}
|
||||
})
|
||||
);
|
||||
await waitFor(() => readdirSync(readyDirectory).length === children.length);
|
||||
writeFileSync(startPath, "start\n");
|
||||
|
||||
const outcomes = await Promise.all(children.map(waitForChild));
|
||||
for (const outcome of outcomes) {
|
||||
assert.equal(outcome.code, 0, outcome.stderr);
|
||||
}
|
||||
} finally {
|
||||
rmSync(cacheRoot, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
const childScript = `
|
||||
import { closeSync, existsSync, openSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
const { withElectronCacheLock } = await import(process.env.TUTTI_ELECTRON_LOCK_MODULE_URL);
|
||||
|
||||
const input = JSON.parse(process.env.TUTTI_ELECTRON_LOCK_INPUT);
|
||||
const readyDirectory = process.env.TUTTI_ELECTRON_LOCK_READY_DIRECTORY;
|
||||
const startPath = process.env.TUTTI_ELECTRON_LOCK_START_PATH;
|
||||
const activePath = process.env.TUTTI_ELECTRON_LOCK_ACTIVE_PATH;
|
||||
writeFileSync(join(readyDirectory, String(process.pid)), "ready\\n");
|
||||
while (!existsSync(startPath)) {
|
||||
await new Promise((resolvePromise) => setTimeout(resolvePromise, 1));
|
||||
}
|
||||
await withElectronCacheLock(input, async () => {
|
||||
const descriptor = openSync(activePath, "wx");
|
||||
try {
|
||||
await new Promise((resolvePromise) => setTimeout(resolvePromise, 30));
|
||||
} finally {
|
||||
closeSync(descriptor);
|
||||
rmSync(activePath, { force: true });
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
async function waitFor(predicate) {
|
||||
const deadline = Date.now() + 5_000;
|
||||
while (!predicate()) {
|
||||
if (Date.now() >= deadline) {
|
||||
throw new Error("timed out waiting for concurrent lock test children");
|
||||
}
|
||||
await new Promise((resolvePromise) => setTimeout(resolvePromise, 5));
|
||||
}
|
||||
}
|
||||
|
||||
function waitForChild(child) {
|
||||
return new Promise((resolvePromise, rejectPromise) => {
|
||||
let stderr = "";
|
||||
child.stderr.on("data", (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on("error", rejectPromise);
|
||||
child.on("close", (code) => {
|
||||
resolvePromise({ code, stderr });
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user