-
Notifications
You must be signed in to change notification settings - Fork 20
[duplicate-code] Duplicate Code Pattern: WASM Guard Function Dispatch Boilerplate #2826
Copy link
Copy link
Closed
Description
Part of duplicate code analysis: #2825
Summary
LabelAgent, LabelResource, and LabelResponse in internal/guard/wasm.go each follow the same ~12-line preamble before doing any function-specific work. This preamble is copy-pasted three times and will drift silently if one copy is updated but the others are not.
Duplication Details
Pattern: WASM guard function dispatch preamble
- Severity: Medium
- Occurrences: 3 functions
- Locations:
internal/guard/wasm.go–LabelAgent(~lines 604–620)internal/guard/wasm.go–LabelResource(~lines 673–690)internal/guard/wasm.go–LabelResponse(~lines 715–733)
Repeated block (simplified):
// Serialize access to the WASM module
g.mu.Lock()
defer g.mu.Unlock()
// Update backend caller for this request
g.backend = backend
// Build input map
input := map[string]interface{}{...}
if caps != nil {
input["capabilities"] = caps
}
// Marshal input
inputJSON, err := json.Marshal(input)
if err != nil {
return ..., fmt.Errorf("failed to marshal input: %w", err)
}
logWasm.Printf("... input JSON (%d bytes): %s", len(inputJSON), string(inputJSON))
// Call WASM function
resultJSON, err := g.callWasmFunction(ctx, "<func_name>", inputJSON)
if err != nil {
return ..., err
}Each function deviates only in the input map keys and the response-parsing step, making the shared preamble a clear candidate for extraction.
Impact Analysis
- Maintainability: A change to the locking strategy, backend update, or
capsinjection must be applied identically in three places. - Bug Risk: Medium — a future change that adds, say, a timeout or tracing span to the preamble will likely miss one of the three functions.
- Code Bloat: ~36 extra lines of duplicate preamble.
Refactoring Recommendations
-
Extract
callWasmGuardFunctionhelper// callWasmGuardFunction serialises WASM access, updates the backend reference, // marshals inputData, calls the named WASM function, and returns the raw result. func (g *WasmGuard) callWasmGuardFunction( ctx context.Context, funcName string, backend BackendCaller, inputData map[string]interface{}, ) ([]byte, error) { g.mu.Lock() defer g.mu.Unlock() g.backend = backend inputJSON, err := json.Marshal(inputData) if err != nil { return nil, fmt.Errorf("failed to marshal %s input: %w", funcName, err) } logWasm.Printf("%s input JSON (%d bytes): %s", funcName, len(inputJSON), string(inputJSON)) return g.callWasmFunction(ctx, funcName, inputJSON) }
-
Each public method then becomes:
- Build the function-specific
inputmap - Call
g.callWasmGuardFunction(ctx, "label_xxx", backend, input) - Parse the returned
resultJSON - Estimated effort: ~1 hour; risk: low (pure refactor, no logic change)
- Build the function-specific
Implementation Checklist
- Review all three function preambles to confirm they are structurally identical
- Extract
callWasmGuardFunctionhelper - Update
LabelAgent,LabelResource,LabelResponseto use the helper - Update tests to confirm no behavioural change
- Verify no functionality broken
Parent Issue
See parent analysis report: #2825
Related to #2825
Generated by Duplicate Code Detector · ◷
- expires on Apr 6, 2026, 6:10 AM UTC
Reactions are currently unavailable
Metadata
Metadata
Assignees
Type
Fields
Give feedbackNo fields configured for issues without a type.