diff --git a/packages/wrangler/package.json b/packages/wrangler/package.json index 330dee977196..dac3648989be 100644 --- a/packages/wrangler/package.json +++ b/packages/wrangler/package.json @@ -74,6 +74,7 @@ "@esbuild-plugins/node-modules-polyfill": "^0.2.2", "blake3-wasm": "^2.1.5", "chokidar": "^3.5.3", + "date-fns": "^3.6.0", "esbuild": "0.17.19", "miniflare": "workspace:*", "nanoid": "^3.3.3", diff --git a/packages/wrangler/src/dev-registry.ts b/packages/wrangler/src/dev-registry.ts index 6accd8434286..a38a62e5775c 100644 --- a/packages/wrangler/src/dev-registry.ts +++ b/packages/wrangler/src/dev-registry.ts @@ -1,13 +1,23 @@ import events from "node:events"; -import { mkdir, readdir, readFile, unlink, writeFile } from "node:fs/promises"; +import { utimesSync } from "node:fs"; +import { + mkdir, + readdir, + readFile, + stat, + unlink, + writeFile, +} from "node:fs/promises"; import { createServer } from "node:http"; import net from "node:net"; import path from "node:path"; import bodyParser from "body-parser"; import { watch } from "chokidar"; +import { subDays } from "date-fns"; import express from "express"; import { createHttpTerminator } from "http-terminator"; import { fetch } from "undici"; +import { version as wranglerVersion } from "../package.json"; import { FILE_BASED_REGISTRY } from "./experimental-flags"; import { getGlobalWranglerConfigPath } from "./global-wrangler-config-path"; import { logger } from "./logger"; @@ -31,6 +41,8 @@ let globalTerminator: HttpTerminator; let globalWatcher: ReturnType | undefined; let globalWorkers: WorkerRegistry | undefined; +const heartbeats = new Map>(); + export type WorkerRegistry = Record; export type WorkerEntrypointsDefinition = Record< @@ -56,10 +68,18 @@ async function loadWorkerDefinitions(): Promise { const newWorkers = new Set(); const workerDefinitions = await readdir(DEV_REGISTRY_PATH); for (const workerName of workerDefinitions) { - globalWorkers[workerName] = JSON.parse( - await readFile(path.join(DEV_REGISTRY_PATH, workerName), "utf8") + const file = await readFile( + path.join(DEV_REGISTRY_PATH, workerName), + "utf8" ); - newWorkers.add(workerName); + const stats = await stat(path.join(DEV_REGISTRY_PATH, workerName)); + // Cleanup old workers + if (stats.mtime < subDays(new Date(), 1)) { + await unregisterWorker(workerName); + } else { + globalWorkers[workerName] = JSON.parse(file); + newWorkers.add(workerName); + } } for (const worker of Object.keys(globalWorkers)) { @@ -171,6 +191,9 @@ export async function startWorkerRegistry() { export async function stopWorkerRegistry() { if (FILE_BASED_REGISTRY()) { await globalWatcher?.close(); + for (const heartbeat of heartbeats) { + clearInterval(heartbeat[1]); + } return; } await globalTerminator?.terminate(); @@ -185,10 +208,23 @@ export async function registerWorker( definition: WorkerDefinition ) { if (FILE_BASED_REGISTRY()) { + const existingHeartbeat = heartbeats.get(name); + if (existingHeartbeat) { + clearInterval(existingHeartbeat); + } await mkdir(DEV_REGISTRY_PATH, { recursive: true }); await writeFile( path.join(DEV_REGISTRY_PATH, name), - JSON.stringify(definition, null, 2) + // We don't currently do anything with the stored Wrangler version, + // but if we need to make breaking changes to this format in the future + // we can use this field to present useful messaging + JSON.stringify({ ...definition, wranglerVersion }, null, 2) + ); + heartbeats.set( + name, + setInterval(() => { + utimesSync(path.join(DEV_REGISTRY_PATH, name), new Date(), new Date()); + }, 30_000) ); return; } @@ -223,6 +259,10 @@ export async function registerWorker( export async function unregisterWorker(name: string) { if (FILE_BASED_REGISTRY()) { await unlink(path.join(DEV_REGISTRY_PATH, name)); + const existingHeartbeat = heartbeats.get(name); + if (existingHeartbeat) { + clearInterval(existingHeartbeat); + } return; } try { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d472c8741b7..3bd62efad221 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1572,6 +1572,9 @@ importers: chokidar: specifier: ^3.5.3 version: 3.5.3 + date-fns: + specifier: ^3.6.0 + version: 3.6.0 esbuild: specifier: 0.17.19 version: 0.17.19 @@ -5738,6 +5741,9 @@ packages: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} + date-fns@3.6.0: + resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} + date-time@3.1.0: resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} engines: {node: '>=6'} @@ -13336,8 +13342,8 @@ snapshots: '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0) eslint-plugin-jest: 26.9.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) eslint-plugin-jest-dom: 4.0.3(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.0) @@ -15458,6 +15464,8 @@ snapshots: dependencies: '@babel/runtime': 7.22.5 + date-fns@3.6.0: {} + date-time@3.1.0: dependencies: time-zone: 1.0.0 @@ -15996,13 +16004,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0): dependencies: debug: 4.3.4(supports-color@9.2.2) enhanced-resolve: 5.14.1 eslint: 8.57.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0) get-tsconfig: 4.6.0 globby: 13.1.4 is-core-module: 2.13.0 @@ -16014,14 +16022,14 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 5.62.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -16103,7 +16111,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0): dependencies: array-includes: 3.1.6 array.prototype.flat: 1.3.1 @@ -16112,7 +16120,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.57.0))(eslint@8.57.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -17187,13 +17195,6 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.0(supports-color@9.2.2) - debug: 4.3.5(supports-color@9.2.2) - transitivePeerDependencies: - - supports-color - https-proxy-agent@7.0.2(supports-color@9.2.2): dependencies: agent-base: 7.1.0(supports-color@9.2.2) @@ -18816,7 +18817,7 @@ snapshots: debug: 4.3.5(supports-color@9.2.2) get-uri: 6.0.1 http-proxy-agent: 7.0.0 - https-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.2(supports-color@9.2.2) pac-resolver: 7.0.0 socks-proxy-agent: 8.0.2 transitivePeerDependencies: @@ -19269,7 +19270,7 @@ snapshots: agent-base: 7.1.0(supports-color@9.2.2) debug: 4.3.5(supports-color@9.2.2) http-proxy-agent: 7.0.0 - https-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.2(supports-color@9.2.2) lru-cache: 7.18.3 pac-proxy-agent: 7.0.1 proxy-from-env: 1.1.0