Description
pkg/service/replay/replay.go is currently the largest file in the codebase at 4,621 lines / 188 KB, containing 75 functions. The most critical hotspot is RunTestSet() — a single function spanning 2,168 lines (lines 1001–3169).
Within RunTestSet, the Docker Compose branch (lines ~1184–1401) and the non-Docker Compose branch (lines ~1403–1570) contain nearly identical blocks of ~150 lines performing the same mock-loading pipeline:
- Call
determineMockingStrategy()
- Build
mocksThatHaveMappings / mocksWeNeed maps
- Call
GetMocks() with time-range filtering
- Call
addKinds() on filtered + unfiltered mocks
- Extract telemetry domains from mocks
- Call
MockMutator.AfterGetMocks() + rebalanceReusableMocks()
- Call
StoreMocks() on the instrumentation
- Build
OutgoingOptions struct and call MockOutgoing()
- Call
SendMockFilterParamsToAgent()
- Handle
FallBackOnMiss deprecation notice
This duplication means that every bug fix or feature change to mock loading must be applied in two places, and the two branches have already begun to drift subtly (e.g., InitSortCounter only in the non-compose branch, MakeAgentReadyForDockerCompose only in the compose branch).
Evidence of Duplication
The Docker Compose branch (starting ~line 1297) and the non-Docker-Compose branch (starting ~line 1405) both execute this identical sequence:
go useMappingBased, expectedTestMockMappings = r.determineMockingStrategy(ctx, testSetID, isMappingEnabled) mocksThatHaveMappings := make(map[string]bool) mocksWeNeed := make(map[string]bool) if isMappingEnabled && len(expectedTestMockMappings) > 0 { for _, mocks := range expectedTestMockMappings { for _, m := range mocks { mocksThatHaveMappings[m.Name] = true } } // ... selectedTests filtering ... } filteredMocks, unfilteredMocks, err := r.GetMocks(ctx, testSetID, ...) addKinds(filteredMocks); addKinds(unfilteredMocks) // ... telemetry extraction ... err = r.instrumentation.StoreMocks(ctx, filteredMocks, unfilteredMocks) err = r.instrumentation.MockOutgoing(runTestSetCtx, models.OutgoingOptions{...}) err = r.SendMockFilterParamsToAgent(ctx, ...)
Broader Context — File Size
The top 5 largest .go files in the codebase:
| File |
Lines |
Size |
pkg/service/replay/replay.go |
4,621 |
188 KB |
pkg/agent/proxy/proxy.go |
4,159 |
183 KB |
pkg/util.go |
4,050 |
141 KB |
pkg/models/postgres_v3_cell.go |
3,181 |
115 KB |
pkg/agent/proxy/integrations/mysql/replayer/match.go |
2,776 |
112 KB |
This issue focuses on replay.go as the most impactful starting point because RunTestSet is the central function in the test-replay critical path and its duplication is the most dangerous kind — it's not just dead code, it's actively maintained logic that can (and has started to) drift.
Proposed Refactoring
-
Extract prepareMocksForTestSet() — A new method on *Replayer that encapsulates steps 1–10 above. Both branches call it with their branch-specific parameters (e.g., compose-only calls like MakeAgentReadyForDockerCompose happen outside this function).
-
Extract setupAppLifecycleMonitor() — The app-launch + error-channel goroutine pair (lines 1186–1223 and 1516–1570) is also duplicated; it can be unified with a boolean flag for compose-specific behavior.
-
Consider splitting RunTestSet further into phases: setup -> mock-loading -> test-loop -> reporting -> pruning. Each phase is already implicitly separated by comments but lives in one monolithic function.
Impact
- Reduced maintenance burden: Bug fixes to mock loading apply once, not twice
- Drift prevention: Eliminates a class of bugs where one branch gets a fix and the other doesn't
- Reviewability: A 2,168-line function is extremely hard to review in PRs
- Testability: Extracted functions can be unit-tested independently (the project already does this for
buildExpectedMockInfos, buildActualMockInfos, etc.)
Description
pkg/service/replay/replay.gois currently the largest file in the codebase at 4,621 lines / 188 KB, containing 75 functions. The most critical hotspot isRunTestSet()— a single function spanning 2,168 lines (lines 1001–3169).Within
RunTestSet, the Docker Compose branch (lines ~1184–1401) and the non-Docker Compose branch (lines ~1403–1570) contain nearly identical blocks of ~150 lines performing the same mock-loading pipeline:determineMockingStrategy()mocksThatHaveMappings/mocksWeNeedmapsGetMocks()with time-range filteringaddKinds()on filtered + unfiltered mocksMockMutator.AfterGetMocks()+rebalanceReusableMocks()StoreMocks()on the instrumentationOutgoingOptionsstruct and callMockOutgoing()SendMockFilterParamsToAgent()FallBackOnMissdeprecation noticeThis duplication means that every bug fix or feature change to mock loading must be applied in two places, and the two branches have already begun to drift subtly (e.g.,
InitSortCounteronly in the non-compose branch,MakeAgentReadyForDockerComposeonly in the compose branch).Evidence of Duplication
The Docker Compose branch (starting ~line 1297) and the non-Docker-Compose branch (starting ~line 1405) both execute this identical sequence:
go useMappingBased, expectedTestMockMappings = r.determineMockingStrategy(ctx, testSetID, isMappingEnabled) mocksThatHaveMappings := make(map[string]bool) mocksWeNeed := make(map[string]bool) if isMappingEnabled && len(expectedTestMockMappings) > 0 { for _, mocks := range expectedTestMockMappings { for _, m := range mocks { mocksThatHaveMappings[m.Name] = true } } // ... selectedTests filtering ... } filteredMocks, unfilteredMocks, err := r.GetMocks(ctx, testSetID, ...) addKinds(filteredMocks); addKinds(unfilteredMocks) // ... telemetry extraction ... err = r.instrumentation.StoreMocks(ctx, filteredMocks, unfilteredMocks) err = r.instrumentation.MockOutgoing(runTestSetCtx, models.OutgoingOptions{...}) err = r.SendMockFilterParamsToAgent(ctx, ...)Broader Context — File Size
The top 5 largest
.gofiles in the codebase:pkg/service/replay/replay.gopkg/agent/proxy/proxy.gopkg/util.gopkg/models/postgres_v3_cell.gopkg/agent/proxy/integrations/mysql/replayer/match.goThis issue focuses on
replay.goas the most impactful starting point becauseRunTestSetis the central function in the test-replay critical path and its duplication is the most dangerous kind — it's not just dead code, it's actively maintained logic that can (and has started to) drift.Proposed Refactoring
Extract
prepareMocksForTestSet()— A new method on*Replayerthat encapsulates steps 1–10 above. Both branches call it with their branch-specific parameters (e.g., compose-only calls likeMakeAgentReadyForDockerComposehappen outside this function).Extract
setupAppLifecycleMonitor()— The app-launch + error-channel goroutine pair (lines 1186–1223 and 1516–1570) is also duplicated; it can be unified with a boolean flag for compose-specific behavior.Consider splitting
RunTestSetfurther into phases: setup -> mock-loading -> test-loop -> reporting -> pruning. Each phase is already implicitly separated by comments but lives in one monolithic function.Impact
buildExpectedMockInfos,buildActualMockInfos, etc.)