Persist wazero compilation cache and warn on unsafe direct-memory fallback#5243
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/20b69fbe-0648-4589-92c8-b30e7f5128a3 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/20b69fbe-0648-4589-92c8-b30e7f5128a3 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/20b69fbe-0648-4589-92c8-b30e7f5128a3 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/20b69fbe-0648-4589-92c8-b30e7f5128a3 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/20b69fbe-0648-4589-92c8-b30e7f5128a3 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds support for a persisted, disk-backed wazero compilation cache and wires it through CLI flags/env vars so repeated guard loads avoid redundant compilation work across runs.
Changes:
- Introduces a configurable process-wide wazero
CompilationCache, including a new--wasm-cache-dirflag andMCP_GATEWAY_WASM_CACHE_DIRenv var. - Updates command startup paths (gateway + proxy) to configure the global cache and adds tests for defaulting/overrides.
- Improves WASM guard behavior/observability (module naming; one-time warning when falling back to direct linear-memory buffers).
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents the new persisted wazero compilation cache under the log directory. |
| internal/guard/wasm.go | Adds global compilation cache configuration and uses guard name for module naming. |
| internal/guard/wasm_test.go | Adds coverage for reconfiguring the global cache to a disk-backed directory. |
| internal/guard/wasm_parse.go | Emits a one-time warning when using the direct memory fallback path and clarifies memory-growth behavior. |
| internal/config/config_payload.go | Adds a constant for the default wazero cache directory name. |
| internal/cmd/root.go | Configures the global wazero compilation cache during gateway startup. |
| internal/cmd/proxy.go | Adds --wasm-cache-dir to proxy mode and configures/closes the global cache. |
| internal/cmd/proxy_test.go | Verifies the new proxy flag is registered and defaults correctly. |
| internal/cmd/flags.go | Adds shell completion support for --wasm-cache-dir. |
| internal/cmd/flags_test.go | Verifies the new flag is registered. |
| internal/cmd/flags_logging.go | Adds --wasm-cache-dir / env resolution logic shared by commands. |
| internal/cmd/flags_logging_test.go | Adds unit tests for defaulting and precedence logic. |
| docs/ENVIRONMENT_VARIABLES.md | Documents MCP_GATEWAY_WASM_CACHE_DIR. |
| AGENTS.md | Documents MCP_GATEWAY_WASM_CACHE_DIR for agent workflows. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
internal/cmd/proxy.go:177
- CloseGlobalCompilationCache is deferred here, but proxy mode doesn’t explicitly close the WASM guard/runtime before closing the compilation cache. wasm.go documents that closing the cache while guards are still active is undefined behavior. Consider adding an explicit proxy shutdown that closes the guard (e.g., a Close method on proxy.Server or a type-asserted Close(ctx) call) and run it before closing the global compilation cache.
cleanupCtx := context.WithoutCancel(ctx)
defer func() {
if err := guard.CloseGlobalCompilationCache(cleanupCtx); err != nil {
logger.LogError("shutdown", "Failed to close WASM compilation cache: %v", err)
}
internal/cmd/root.go:157
- ConfigureGlobalCompilationCache errors are treated as fatal here, unlike logger.InitGatewayLoggers which explicitly warns and falls back when the log directory can’t be created. If the default cache directory is not writable, startup will abort. Consider falling back to an in-memory cache (dir="") with a warning when the disk-backed cache cannot be initialized.
if err := guard.ConfigureGlobalCompilationCache(ctx, resolvedWasmCacheDir); err != nil {
return fmt.Errorf("failed to configure WASM compilation cache: %w", err)
}
- Files reviewed: 14/14 changed files
- Comments generated: 3
| globalCompilationCache = cache | ||
| globalCompilationCacheMu.Unlock() | ||
|
|
||
| if oldCache == nil { | ||
| return nil | ||
| } | ||
|
|
||
| if err := oldCache.Close(ctx); err != nil { | ||
| closeReplacementErr := cache.Close(ctx) | ||
| if closeReplacementErr != nil { | ||
| return errors.Join( | ||
| fmt.Errorf("failed to close previous compilation cache: %w", err), | ||
| fmt.Errorf("failed to close replacement compilation cache: %w", closeReplacementErr), | ||
| ) | ||
| } | ||
| return fmt.Errorf("failed to close previous compilation cache: %w", err) | ||
| } | ||
|
|
| resolvedWasmCacheDir := resolveWasmCacheDir(cmd.Flags().Changed("wasm-cache-dir"), proxyWasmCacheDir, proxyLogDir) | ||
| if err := guard.ConfigureGlobalCompilationCache(ctx, resolvedWasmCacheDir); err != nil { | ||
| return fmt.Errorf("failed to configure WASM compilation cache: %w", err) | ||
| } |
| logger.LogInfoMd("startup", "Starting MCPG with config: %s, listen: %s, log-dir: %s", configSource, listenAddr, logDir) | ||
| debugLog.Printf("Starting MCPG with config: %s, listen: %s", configSource, listenAddr) | ||
|
|
||
| resolvedWasmCacheDir := resolveWasmCacheDir(cmd.Flags().Changed("wasm-cache-dir"), wasmCacheDir, logDir) |
|
@copilot merge main and address the review feedback |
…-wazero-module Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/0884d746-0517-4cc9-88e4-462b8113fde4 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Merged Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
The gateway uses
tetratelabs/wazeroto run WASM DIFC guards in-process. This updates the guard runtime to persist compilation artifacts across restarts and makes the allocator fallback path more explicit and diagnosable.Persisted wazero cache
--wasm-cache-dirandMCP_GATEWAY_WASM_CACHE_DIR<log-dir>/wazero-cacheSafer guard execution behavior
alloc/deallocexports are missing and execution falls back to direct linear-memory placement"guard"Documentation of memory ownership
Coverage updates
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
example.com/tmp/go-build904193801/b509/launcher.test /tmp/go-build904193801/b509/launcher.test -test.testlogfile=/tmp/go-build904193801/b509/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true uf@v1.36.11/type-errorsas om/segmentio/asm-ifaceassert x_amd64/vet /tmp/go-build119/opt/hostedtoolcache/go/1.25.9/x64/pkg/tool/linux_amd64/vet ce/internal/obse-unsafeptr=false x86_64-linux-gnu-unreachable=false x_amd64/vet 3325�� g_.a ache/go/1.25.9/x64/src/compress/flate/deflate.go-nolocalimports x_amd64/vet -I ntio/asm/ascii -imultiarch x_amd64/vet(dns block)/tmp/go-build1634526129/b513/launcher.test /tmp/go-build1634526129/b513/launcher.test -test.testlogfile=/tmp/go-build1634526129/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s(dns block)invalid-host-that-does-not-exist-12345.com/tmp/go-build904193801/b491/config.test /tmp/go-build904193801/b491/config.test -test.testlogfile=/tmp/go-build904193801/b491/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true @v1.43.0/semconv/v1.27.0/attribute_group.go @v1.43.0/semconv/v1.27.0/doc.go x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet 3325�� g_.a ache/go/1.25.9/x64/src/log/slog/internal/buffer/-nolocalimports x_amd64/vet --gdwarf-5 telabs/wazero/in-atomic -o x_amd64/vet(dns block)/tmp/go-build1634526129/b495/config.test /tmp/go-build1634526129/b495/config.test -test.testlogfile=/tmp/go-build1634526129/b495/testlog.txt -test.paniconexit0 -test.timeout=10m0s 7478�� echo "Running li-nxv cfg ep/bin/linux-x64/rg -c=4 -nolocalimports -importcfg ep/bin/linux-x64-buildtags 7478�� /tmp/go-build302-errorsas /home/REDACTED/go/-ifaceassert x_amd64/compile 64/src/runtime/cbash 7RwcO3vCT de/node/bin/as x_amd64/compile(dns block)nonexistent.local/tmp/go-build904193801/b509/launcher.test /tmp/go-build904193801/b509/launcher.test -test.testlogfile=/tmp/go-build904193801/b509/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true uf@v1.36.11/type-errorsas om/segmentio/asm-ifaceassert x_amd64/vet /tmp/go-build119/opt/hostedtoolcache/go/1.25.9/x64/pkg/tool/linux_amd64/vet ce/internal/obse-unsafeptr=false x86_64-linux-gnu-unreachable=false x_amd64/vet 3325�� g_.a ache/go/1.25.9/x64/src/compress/flate/deflate.go-nolocalimports x_amd64/vet -I ntio/asm/ascii -imultiarch x_amd64/vet(dns block)/tmp/go-build1634526129/b513/launcher.test /tmp/go-build1634526129/b513/launcher.test -test.testlogfile=/tmp/go-build1634526129/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s(dns block)slow.example.com/tmp/go-build904193801/b509/launcher.test /tmp/go-build904193801/b509/launcher.test -test.testlogfile=/tmp/go-build904193801/b509/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true uf@v1.36.11/type-errorsas om/segmentio/asm-ifaceassert x_amd64/vet /tmp/go-build119/opt/hostedtoolcache/go/1.25.9/x64/pkg/tool/linux_amd64/vet ce/internal/obse-unsafeptr=false x86_64-linux-gnu-unreachable=false x_amd64/vet 3325�� g_.a ache/go/1.25.9/x64/src/compress/flate/deflate.go-nolocalimports x_amd64/vet -I ntio/asm/ascii -imultiarch x_amd64/vet(dns block)/tmp/go-build1634526129/b513/launcher.test /tmp/go-build1634526129/b513/launcher.test -test.testlogfile=/tmp/go-build1634526129/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s(dns block)this-host-does-not-exist-12345.com/tmp/go-build904193801/b518/mcp.test /tmp/go-build904193801/b518/mcp.test -test.testlogfile=/tmp/go-build904193801/b518/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true .cfg rg/x/net@v0.52.0-ifaceassert x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet .cfg�� 3325167/b384/_pkg_.a -I x_amd64/vet --gdwarf-5 g/grpc/resolver -o x_amd64/vet(dns block)/tmp/go-build1634526129/b522/mcp.test /tmp/go-build1634526129/b522/mcp.test -test.testlogfile=/tmp/go-build1634526129/b522/testlog.txt -test.paniconexit0 -test.timeout=10m0s /tmp��(dns block)If you need me to access, download, or install something from one of these locations, you can either: