From eb8a5ff91e3c72ced0fed37b8d9adbaa9d335bbc Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Fri, 5 Dec 2025 00:50:10 +1000 Subject: [PATCH] feat: add persistent Deno cache to Railway executor for faster tool loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Set DENO_DIR=/app/.deno_cache to persist module cache - Pre-cache common dependencies (zod-to-json-schema, ai, zod) during build - Add Railway volume configuration for /app/.deno_cache - Improve logging to show cache hits vs network downloads - Add --allow-read and --allow-write permissions for cache access This dramatically reduces tool loading time after the first import. Dependencies are downloaded once and reused across all subsequent requests. Example: ctx-zip with 200+ dependencies will only download once instead of on every chat request. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/railway-executor/Dockerfile | 20 ++++++++++++++++++-- apps/railway-executor/railway.toml | 14 ++++++++++++++ apps/railway-executor/server.ts | 9 ++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 apps/railway-executor/railway.toml diff --git a/apps/railway-executor/Dockerfile b/apps/railway-executor/Dockerfile index 6ccef57..6979815 100644 --- a/apps/railway-executor/Dockerfile +++ b/apps/railway-executor/Dockerfile @@ -4,11 +4,27 @@ FROM denoland/deno:1.39.0 # Set working directory WORKDIR /app -# Copy the server file +# Set Deno cache directory to persist across requests +ENV DENO_DIR=/app/.deno_cache + +# Create cache directory +RUN mkdir -p /app/.deno_cache + +# Copy files COPY server.ts . +COPY deno.json . + +# Pre-cache zod-to-json-schema (used by server.ts) +RUN deno cache --reload \ + https://esm.sh/zod-to-json-schema@3.25.0 + +# Pre-cache common AI SDK dependencies to speed up first loads +RUN deno cache --reload \ + https://esm.sh/ai@5.0.83 \ + https://esm.sh/zod@3.22.0 || true # Expose port (Railway will set PORT env var) EXPOSE 3002 # Run the Deno server -CMD ["deno", "run", "--allow-net", "--allow-env", "server.ts"] +CMD ["deno", "run", "--allow-net", "--allow-env", "--allow-read", "--allow-write", "server.ts"] diff --git a/apps/railway-executor/railway.toml b/apps/railway-executor/railway.toml new file mode 100644 index 0000000..c6947a3 --- /dev/null +++ b/apps/railway-executor/railway.toml @@ -0,0 +1,14 @@ +[build] +builder = "dockerfile" +dockerfilePath = "Dockerfile" + +[deploy] +startCommand = "deno run --allow-net --allow-env --allow-read --allow-write server.ts" +restartPolicyType = "on_failure" +restartPolicyMaxRetries = 10 + +# Mount persistent volume for Deno cache +# This persists the cache across deploys and restarts +[[volumes]] +mountPath = "/app/.deno_cache" +name = "deno-cache" diff --git a/apps/railway-executor/server.ts b/apps/railway-executor/server.ts index dabc676..f13ba60 100644 --- a/apps/railway-executor/server.ts +++ b/apps/railway-executor/server.ts @@ -104,7 +104,14 @@ async function loadAndDescribe(req: Request): Promise { } else { // Dynamic import from esm.sh (Deno supports this natively!) const url = importUrl || `https://esm.sh/${packageName}@${version}`; - console.log(`📦 Importing: ${url}`); + + // Log cache status for visibility + const isFirstImport = !moduleCache.has(cacheKey); + if (isFirstImport) { + console.log(`📦 Importing from network (will be cached by Deno): ${url}`); + } else { + console.log(`✅ Using in-memory cache: ${url}`); + } const module = await import(url); let rawExport = module[exportName];