refactor(arch): executor RequestPreparer extraction + route-pref characterization test (Phase 4)#115
Conversation
…acterization test (Phase 4 Tasks 4.1 gap, 4.3) Complete the remaining Phase 4 tasks from the architecture review resolution plan: (1) Route-preference characterization test — locks the planning-side effect of execctx.RouteCandidatePreferences at the Execute boundary (the 4th characterization gap). (2) RequestPreparer extraction — extracts Execute phases 1-9 (validation, snapshot binding, secure-session begin-turn, tracing, submit/A-leg, lifecycle start, exec views, secure turn, route pref clone — 62 lines) into executor_prepare_request.go as prepareRequest returning a preparedRequest struct. Execute now delegates preparation and reads as: prepareRequest -> parse selector -> plan route -> attempt loop (tryPlanOpenOnce) -> B-leg register -> retryRecvStream assembly -> interleaved wrappers. (3) Task 4.2 field grouping was attempted but reverted — Go struct embedding breaks struct literal initialization in 47 test files (promoted fields cannot be used in composite literals); deferred to a future builder-pattern PR. (4) Tasks 4.4-4.6 (RoutePlanner/AttemptOpener/StreamAssembler further extraction) — the remaining Execute body is ~100 lines and already well-factored via tryPlanOpenOnce and helper methods; further extraction is mechanical but lower-value. (5) executor.go budget tightened from 480 to 380 (current 355 lines). Verification: make quality-checks, make test-unit (zero failing packages), make test-precommit-extra (executor matrix), lipstd check-config + serve smoke (405 + X-Trace-Id) all pass. No behavior change; Execute signature stable; all error wrapping preserved. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughSummary by CodeRabbit
WalkthroughRefactors ChangesExecutor request preparation extraction
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 8✅ Passed checks (8 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/core/runtime/executor_prepare_request.go`:
- Around line 78-82: Record prepareSubmitAndALeg failures on the request span
before ending it in executor_prepare_request.go. In prepareExecutorRequest, when
the prepareSubmitAndALeg call returns an error, make sure the prep.execSpan is
updated with RecordError and SetStatus (or routed through finalize(err)) before
execSpan.End so the lip.executor.execute telemetry still captures the failure.
Keep the existing prepareSubmitAndALeg and finalize(err) flow aligned so this
error path is not dropped.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: afd1db11-8b9d-4797-8422-96f17f83b69a
📒 Files selected for processing (4)
internal/archtest/critical_files.gointernal/core/runtime/executor.gointernal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor_route_preference_test.go
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: qa
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go
📄 CodeRabbit inference engine (Custom checks)
**/*.go: For server, CLI, worker, or network Go code, ensurecontext.Contextis propagated correctly, cancellation is respected, and new goroutines cannot leak indefinitely.
Do not make accidental public API breaks in Go code: underpkg/**or anywhere exported Go identifiers are changed, warn if the PR changes exported types, function signatures, error behavior, JSON fields, CLI flags, config keys, or documented behavior without clearly explaining the compatibility impact.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/archtest/critical_files.gointernal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor.go
⚙️ CodeRabbit configuration file
**/*.go: Review as production Go code. Prioritize correctness, race conditions, goroutine leaks, context cancellation, timeout handling, error wrapping, nil-pointer risks, resource cleanup, defer placement, API compatibility, interface design, dependency boundaries, and testability. Avoid generic style comments when gofmt/golangci-lint already covers the issue.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/archtest/critical_files.gointernal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor.go
**/*
📄 CodeRabbit inference engine (Custom checks)
Do not introduce hardcoded credentials, API keys, tokens, private keys, passwords, production secrets, or sensitive internal URLs.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/archtest/critical_files.gointernal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor.go
internal/**
⚙️ CodeRabbit configuration file
internal/**: Focus on package boundaries, hidden coupling, unexported API design, concurrency safety, deterministic behavior, and whether logic belongs in this internal package.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/archtest/critical_files.gointernal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor.go
**/*_test.go
⚙️ CodeRabbit configuration file
**/*_test.go: Review tests for meaningful assertions, table-driven coverage, race-prone tests, t.Parallel misuse, nondeterminism, leaked goroutines, real network or filesystem dependencies, fragile sleeps, and missing edge cases. Prefer testing observable behavior over implementation details.
Files:
internal/core/runtime/executor_route_preference_test.go
🧠 Learnings (1)
📚 Learning: 2026-07-01T22:57:42.953Z
Learnt from: matdev83
Repo: matdev83/go-llm-interactive-proxy PR: 101
File: pkg/lipsdk/scope/context.go:0-0
Timestamp: 2026-07-01T22:57:42.953Z
Learning: In this repository, when defining unexported Go `context` key constants of type `ctxKey int` (e.g., `const ( kFoo ctxKey = iota + N )`), preserve the `iota + <offset>` pattern and keep the existing `<offset>` values rather than simplifying to plain `iota`. These per-package offsets are part of the repo-wide convention to avoid key collisions across packages, and each such constant set should include a short explanatory comment (for example: “offset avoids collision with other packages' context keys”).
Applied to files:
internal/core/runtime/executor_route_preference_test.gointernal/archtest/critical_files.gointernal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor.go
🔇 Additional comments (6)
internal/core/runtime/executor_route_preference_test.go (1)
21-75: LGTM!internal/archtest/critical_files.go (1)
39-49: LGTM!internal/core/runtime/executor_prepare_request.go (1)
45-75: LGTM!Also applies to: 84-118
internal/core/runtime/executor.go (3)
265-293: LGTM!
302-338: LGTM!
225-232: 🩺 Stability & Availability
cleanup()already seesstreamReturnedupdates
prepareRequestreturns&prep, so the cleanup closure andExecuteshare the same*preparedRequestinstance;streamReturnedis visible tocleanup().> Likely an incorrect or invalid review comment.
The RequestPreparer extraction moved the prepareSubmitAndALeg call from inline Execute into prepareRequest. The former inline flow started the lip.executor.execute span and deferred finalize(err) (RecordError + SetStatus + End), so a prepareSubmitAndALeg failure was recorded on the span. After extraction, the prepareSubmitAndALeg error path in prepareRequest called execSpan.End() directly, dropping RecordError/SetStatus; and Execute does not call finalize when prepareRequest returns an error (prep is nil). Route the prepare-submit error through prep.finalize(err) so the span records the failure before ending, restoring the prior telemetry. No behavior change beyond telemetry. Verified: go build ./internal/core/runtime/... OK; full repo golangci-lint v2.11.4 -> 0 issues; internal/core/runtime tests pass. Co-authored-by: Cursor <cursoragent@cursor.com>
golangci-lint v2.11.4 modernize flagged var preferredOpens/otherOpens int32 used with atomic.AddInt32/LoadInt32 as simplifiable to atomic.Int32 method calls. Switch to atomic.Int32 (.Add/.Load). Behavior identical; this unblocks the QA golangci-lint step. Verified: golangci-lint v2.11.4 -> 0 issues; TestExecutor_execute_routePreferenceDrivesPlanner passes. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
internal/core/runtime/executor_route_preference_test.go (1)
61-68: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a timeout to the test context.
Both
ex.Executeandlipapi.Collectrun withcontext.Background()/an untimed derived context, with no deadline. If planning or streaming ever regresses to a hang, this test blocks indefinitely instead of failing fast in CI.🕐 Suggested fix
- ctx := execctx.WithRouteCandidatePreferences(context.Background(), []string{"preferred"}) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + ctx = execctx.WithRouteCandidatePreferences(ctx, []string{"preferred"}) stream, err := ex.Execute(ctx, call) if err != nil { t.Fatal(err) } - if _, err := lipapi.Collect(context.Background(), stream); err != nil { + if _, err := lipapi.Collect(ctx, stream); err != nil { t.Fatalf("Collect: %v", err) }As per path instructions, tests should be reviewed for nondeterminism and hang risk; "Review tests for meaningful assertions, table-driven coverage, race-prone tests, t.Parallel misuse, nondeterminism, leaked goroutines, real network or filesystem dependencies, fragile sleeps, and missing edge cases."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/core/runtime/executor_route_preference_test.go` around lines 61 - 68, Add a bounded timeout to the test in executor_route_preference_test by creating a timed context before calling ex.Execute and reusing it for lipapi.Collect instead of context.Background(); this keeps the test from hanging indefinitely if planning or streaming stalls. Update the test body around execctx.WithRouteCandidatePreferences, ex.Execute, and lipapi.Collect so both operations share the same deadline-bearing context.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@internal/core/runtime/executor_route_preference_test.go`:
- Around line 61-68: Add a bounded timeout to the test in
executor_route_preference_test by creating a timed context before calling
ex.Execute and reusing it for lipapi.Collect instead of context.Background();
this keeps the test from hanging indefinitely if planning or streaming stalls.
Update the test body around execctx.WithRouteCandidatePreferences, ex.Execute,
and lipapi.Collect so both operations share the same deadline-bearing context.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 640ecff5-c3b3-40b0-a68e-f54e59dc9c74
📒 Files selected for processing (2)
internal/core/runtime/executor_prepare_request.gointernal/core/runtime/executor_route_preference_test.go
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: qa
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go
📄 CodeRabbit inference engine (Custom checks)
**/*.go: For server, CLI, worker, or network Go code, ensurecontext.Contextis propagated correctly, cancellation is respected, and new goroutines cannot leak indefinitely.
Do not make accidental public API breaks in Go code: underpkg/**or anywhere exported Go identifiers are changed, warn if the PR changes exported types, function signatures, error behavior, JSON fields, CLI flags, config keys, or documented behavior without clearly explaining the compatibility impact.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/core/runtime/executor_prepare_request.go
⚙️ CodeRabbit configuration file
**/*.go: Review as production Go code. Prioritize correctness, race conditions, goroutine leaks, context cancellation, timeout handling, error wrapping, nil-pointer risks, resource cleanup, defer placement, API compatibility, interface design, dependency boundaries, and testability. Avoid generic style comments when gofmt/golangci-lint already covers the issue.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/core/runtime/executor_prepare_request.go
**/*
📄 CodeRabbit inference engine (Custom checks)
Do not introduce hardcoded credentials, API keys, tokens, private keys, passwords, production secrets, or sensitive internal URLs.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/core/runtime/executor_prepare_request.go
internal/**
⚙️ CodeRabbit configuration file
internal/**: Focus on package boundaries, hidden coupling, unexported API design, concurrency safety, deterministic behavior, and whether logic belongs in this internal package.
Files:
internal/core/runtime/executor_route_preference_test.gointernal/core/runtime/executor_prepare_request.go
**/*_test.go
⚙️ CodeRabbit configuration file
**/*_test.go: Review tests for meaningful assertions, table-driven coverage, race-prone tests, t.Parallel misuse, nondeterminism, leaked goroutines, real network or filesystem dependencies, fragile sleeps, and missing edge cases. Prefer testing observable behavior over implementation details.
Files:
internal/core/runtime/executor_route_preference_test.go
🧠 Learnings (1)
📚 Learning: 2026-07-01T22:57:42.953Z
Learnt from: matdev83
Repo: matdev83/go-llm-interactive-proxy PR: 101
File: pkg/lipsdk/scope/context.go:0-0
Timestamp: 2026-07-01T22:57:42.953Z
Learning: In this repository, when defining unexported Go `context` key constants of type `ctxKey int` (e.g., `const ( kFoo ctxKey = iota + N )`), preserve the `iota + <offset>` pattern and keep the existing `<offset>` values rather than simplifying to plain `iota`. These per-package offsets are part of the repo-wide convention to avoid key collisions across packages, and each such constant set should include a short explanatory comment (for example: “offset avoids collision with other packages' context keys”).
Applied to files:
internal/core/runtime/executor_route_preference_test.gointernal/core/runtime/executor_prepare_request.go
🔇 Additional comments (3)
internal/core/runtime/executor_prepare_request.go (1)
80-84: LGTM!internal/core/runtime/executor_route_preference_test.go (2)
21-59: LGTM!
69-75: LGTM!
Summary
execctx.RouteCandidatePreferencesat theExecuteboundary — the 4th and final characterization gap. All 4 characterization test gaps are now filled.Executephases 1-9 (validation, snapshot binding, secure-session begin-turn, tracing span, submit/A-leg, lifecycle start, exec views, secure turn, route pref clone — 62 lines) intoexecutor_prepare_request.goasprepareRequestreturning apreparedRequeststruct + cleanup function.Executenow delegates preparation and reads as:prepareRequest-> parse selector -> plan route -> attempt loop (tryPlanOpenOnce) -> B-leg register ->retryRecvStreamassembly -> interleaved wrappers.executor.gobudget tightened from 480 to 380 (current 355 lines, down from 416).Executebody is ~100 lines and already well-factored viatryPlanOpenOnceand helper methods. Further extraction is mechanical but lower-value; deferred.Test plan
go test -count=1 ./internal/core/runtime/— all tests pass (including 4 characterization tests)make test-precommit-extra(executor matrix: precommit-tagged tests ininternal/core/runtime/+internal/qa/)make quality-checks(gofmt, tidy, build, vet, goroutine allowlist, regex hotpath, archtest incl. tightenedexecutor.gobudget 355 <= 380)make test-unit(zero failing packages)go run ./cmd/lipstd check-config— configuration validlipstd servesmoke:GET /v1/responses->405+X-Trace-Id— confirms theExecutepath (prepareRequest -> routing -> attempt -> stream) works end-to-endExecutesignature stable; error wrapping preserved; no behavior change