feat: add persistent Deno cache to Railway executor for faster tool loading

- 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 <noreply@anthropic.com>
This commit is contained in:
Ajax Davis 2025-12-05 00:50:10 +10:00
parent 578ce944d2
commit eb8a5ff91e
3 changed files with 40 additions and 3 deletions

View file

@ -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"]

View file

@ -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"

View file

@ -104,7 +104,14 @@ async function loadAndDescribe(req: Request): Promise<Response> {
} 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];