perf(self-hosted): acr update 共享一次 install 取代 23 個 worker 各裝 324MB
壓測 2026-06-12 真因:每個 worker 各 pnpm install ~324MB node_modules(23× 重複, 全是 hono+wrangler)→ 好幾分鐘。改成 tarball root 裝一次(hono+wrangler+tier2 額外 zod/mcp-sdk/yaml),各 worker 靠 node 往上 resolve(dry-run 驗證 tier1+tier2 都 bundle 成功)。 207MB×1 取代 324MB×23。疊加 manifest 跳過 → 第二次 update 近乎瞬間。 共享失敗自動退回各 worker 自裝(不破壞既有路徑)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+38
-6
@@ -153,6 +153,35 @@ export async function downloadAndDeploy(
|
||||
return { implemented: true, message: `部署物中找不到任何 wrangler.toml(root=${root})。` };
|
||||
}
|
||||
|
||||
// 2.5 共享依賴:23 個 component worker 的 runtime dep 全是 hono、devDep 全含 wrangler,
|
||||
// 舊版每個 worker 各 install 一份 ~324MB node_modules(23× 重複,壓測 2026-06-12 慢的真因)。
|
||||
// 改成在 tarball root 裝「一次」hono+wrangler;component 目錄靠 node 往上 resolve(已驗證可行)。
|
||||
// → 23×4.4s install 變 1×17s。失敗不致命:退回各 worker 自裝(runWranglerDeploy 仍有 fallback)。
|
||||
let sharedBin = '';
|
||||
try {
|
||||
process.stdout.write(chalk.gray(' → 安裝共享部署依賴(一次,取代每個 worker 各裝)...'));
|
||||
// 含全部 worker 的 runtime deps(tier1 component 只要 hono;tier2 cypher/registry/mcp/kbdb
|
||||
// 另需 zod / @hono/zod-openapi / @modelcontextprotocol/sdk / js-yaml / yaml)→ 全裝 root,
|
||||
// 各 worker 往上 resolve,esbuild bundle 找得到。漏一個會讓該 worker deploy 失敗,故寧可多列。
|
||||
writeFileSync(
|
||||
join(root, 'package.json'),
|
||||
JSON.stringify({ name: 'arcrun-deploy-shared', private: true, type: 'module',
|
||||
dependencies: {
|
||||
hono: '^4.7.0', wrangler: '^4.0.0', zod: '^3.23.0',
|
||||
'@hono/zod-openapi': '^0.18.0', '@modelcontextprotocol/sdk': '^1.0.0',
|
||||
'js-yaml': '^4.1.0', yaml: '^2.4.0',
|
||||
} }),
|
||||
);
|
||||
execFileSync('npm', ['install', '--no-audit', '--no-fund'],
|
||||
{ cwd: root, stdio: ['ignore', 'ignore', 'pipe'] });
|
||||
sharedBin = join(root, 'node_modules', '.bin', 'wrangler');
|
||||
console.log(existsSync(sharedBin) ? chalk.green(' ✓') : chalk.yellow(' ⚠ 退回各 worker 自裝'));
|
||||
if (!existsSync(sharedBin)) sharedBin = '';
|
||||
} catch (e) {
|
||||
const tail = (e as { stderr?: Buffer }).stderr?.toString().trim().split('\n').slice(-2).join(' | ').slice(0, 200) ?? '';
|
||||
console.log(chalk.yellow(` ⚠ 共享安裝失敗,退回各 worker 自裝${tail ? `:${tail}` : ''}`));
|
||||
}
|
||||
|
||||
// 3. 對每個 worker:注入 KV id(+ cypher WORKER_SUBDOMAIN)→ wrangler deploy。tier1 先 tier2 後。
|
||||
// 逐 worker 串流進度(每個含 pnpm install + wrangler deploy,沉默會讓人以為卡住——
|
||||
// 壓測 2026-06-11 richblack 觀察:「D1 ✓」後停很久其實在這個迴圈靜默部署 20+ worker)。
|
||||
@@ -178,7 +207,7 @@ export async function downloadAndDeploy(
|
||||
console.log(chalk.gray(' ⊘ 未變動,跳過'));
|
||||
continue;
|
||||
}
|
||||
runWranglerDeploy(dir, ctx);
|
||||
runWranglerDeploy(dir, ctx, sharedBin);
|
||||
manifest[label] = hash; // 只在成功後記錄 → 失敗者下次必重試
|
||||
saveManifest(manifest);
|
||||
deployed++;
|
||||
@@ -400,16 +429,19 @@ export function stripOfficialOnlyBindings(toml: string): string {
|
||||
return out.join('\n');
|
||||
}
|
||||
|
||||
/** 在 worker 目錄跑 wrangler deploy(用用戶的 CF token + account)。*/
|
||||
function runWranglerDeploy(dir: string, ctx: DeployContext): void {
|
||||
// 先裝依賴(cypher-executor/registry 是 TS,wrangler 內建 esbuild bundle 需 node_modules)
|
||||
if (existsSync(join(dir, 'package.json'))) {
|
||||
/** 在 worker 目錄跑 wrangler deploy(用用戶的 CF token + account)。
|
||||
* sharedBin:root 共享 wrangler binary 路徑(見 downloadAndDeploy 2.5)。有則用它且**跳過本地 install**
|
||||
* (deps 從 root node_modules 往上 resolve);空字串則退回舊行為(各 worker 自裝)。*/
|
||||
function runWranglerDeploy(dir: string, ctx: DeployContext, sharedBin = ''): void {
|
||||
if (!sharedBin && existsSync(join(dir, 'package.json'))) {
|
||||
// fallback:共享安裝失敗時才走這條,各 worker 自裝
|
||||
const installer = existsSync(join(dir, 'pnpm-lock.yaml'))
|
||||
? ['pnpm', 'install', '--frozen-lockfile']
|
||||
: ['npm', 'install', '--no-audit', '--no-fund'];
|
||||
runStep(installer[0], installer.slice(1), dir, process.env);
|
||||
}
|
||||
runStep('wrangler', ['deploy'], dir, {
|
||||
const wranglerCmd = sharedBin || 'wrangler';
|
||||
runStep(wranglerCmd, ['deploy'], dir, {
|
||||
...process.env,
|
||||
CLOUDFLARE_API_TOKEN: ctx.apiToken,
|
||||
CLOUDFLARE_ACCOUNT_ID: ctx.accountId,
|
||||
|
||||
Reference in New Issue
Block a user