Part of duplicate code analysis: #8399
Summary
run() in internal/cmd/root.go and runProxy() in internal/cmd/proxy.go share the same startup/teardown skeleton (signal context → loggers → WASM cache → OTel tracing → create server → HTTP server → serveAndWait) but have diverged. The most impactful divergence is that run() configures the WASM compilation cache but never calls guard.CloseGlobalCompilationCache() at teardown, while runProxy() correctly defers this cleanup.
Duplication Details
Pattern: Diverged startup/teardown structure with missing cleanup in run()
- Severity: Medium
- Occurrences: 1 structural divergence, 1 missing cleanup call
- Locations:
internal/cmd/root.go (lines ~178–184): configureWasmCompilationCache without cleanup
internal/cmd/proxy.go (lines ~165–174): configureWasmCompilationCache with correct defer cleanup
proxy.go (correct):
// internal/cmd/proxy.go
resolvedWasmCacheDir, err := configureWasmCompilationCache(ctx, cmd.Flags().Changed("wasm-cache-dir"), proxyWasmCacheDir, proxyLogDir, logger.StartupWarn)
if err != nil {
return err
}
cleanupCtx := context.WithoutCancel(ctx)
defer func() {
if err := guard.CloseGlobalCompilationCache(cleanupCtx); err != nil {
logger.LogError("shutdown", "Failed to close WASM compilation cache: %v", err)
}
}()
logger.LogInfo("startup", "WASM compilation cache directory: %s", resolvedWasmCacheDir)
root.go (missing cleanup):
// internal/cmd/root.go
resolvedWasmCacheDir, cacheErr := configureWasmCompilationCache(ctx, cmd.Flags().Changed("wasm-cache-dir"), wasmCacheDir, logDir, logger.StartupWarn)
if cacheErr != nil {
return cacheErr
}
logger.StartupInfo("WASM compilation cache directory: %s", resolvedWasmCacheDir)
// ^^^ No defer for guard.CloseGlobalCompilationCache — the cache is never flushed/closed
Additional divergences:
Impact Analysis
- Bug Risk: The missing
guard.CloseGlobalCompilationCache() in root.go means the disk-backed wazero compilation cache is never properly closed/flushed on normal gateway shutdown. For in-memory caches this has no visible effect, but for disk-backed caches it could leave transient state
- Maintainability: Changes to the startup pattern in one command need to be manually mirrored in the other — the divergence makes this error-prone
Refactoring Recommendations
- Add missing cleanup to
run() in root.go:
// After configureWasmCompilationCache in run():
cleanupCtx := context.WithoutCancel(ctx)
defer func() {
if err := guard.CloseGlobalCompilationCache(cleanupCtx); err != nil {
logger.LogError("shutdown", "Failed to close WASM compilation cache: %v", err)
}
}()
- Consider extracting shared startup logic into a helper (e.g.,
initCommonRuntime(ctx, wasmCacheDir, logDir, warnFn)) that returns a cleanup function — used by both run() and runProxy(). This ensures future changes to the startup sequence are applied consistently.
Implementation Checklist
Parent Issue
See parent analysis report: #8399
Related to #8399
Generated by Duplicate Code Detector · 194.3 AIC · ⊞ 8.5K · ◷
Part of duplicate code analysis: #8399
Summary
run()ininternal/cmd/root.goandrunProxy()ininternal/cmd/proxy.goshare the same startup/teardown skeleton (signal context → loggers → WASM cache → OTel tracing → create server → HTTP server →serveAndWait) but have diverged. The most impactful divergence is thatrun()configures the WASM compilation cache but never callsguard.CloseGlobalCompilationCache()at teardown, whilerunProxy()correctly defers this cleanup.Duplication Details
Pattern: Diverged startup/teardown structure with missing cleanup in
run()internal/cmd/root.go(lines ~178–184):configureWasmCompilationCachewithout cleanupinternal/cmd/proxy.go(lines ~165–174):configureWasmCompilationCachewith correct defer cleanupproxy.go(correct):root.go(missing cleanup):Additional divergences:
proxy.gouseslog.Printf + logger.LogInfo(old pattern);root.gouseslogger.StartupInfo(new consolidated pattern) — see sub-issue [duplicate-code] Duplicate Code Pattern: Dual logging bypassing logger.StartupInfo in proxy.go #8400proxy.gouseslogger.LogInfo("startup", ...)for the WASM cache line;root.gouseslogger.StartupInfo— minor inconsistencyImpact Analysis
guard.CloseGlobalCompilationCache()inroot.gomeans the disk-backed wazero compilation cache is never properly closed/flushed on normal gateway shutdown. For in-memory caches this has no visible effect, but for disk-backed caches it could leave transient stateRefactoring Recommendations
run()inroot.go:initCommonRuntime(ctx, wasmCacheDir, logDir, warnFn)) that returns a cleanup function — used by bothrun()andrunProxy(). This ensures future changes to the startup sequence are applied consistently.Implementation Checklist
defer guard.CloseGlobalCompilationCache(cleanupCtx)torun()inroot.gologger.StartupInfoinproxy.go(covered by [duplicate-code] Duplicate Code Pattern: Dual logging bypassing logger.StartupInfo in proxy.go #8400)initCommonRuntimehelper would reduce structural divergencemake agent-finishedto verify no regressionsParent Issue
See parent analysis report: #8399
Related to #8399