blockassembly: prevent Start hanging on pre-ready gRPC failures#940
Conversation
Benchmark Comparison ReportBaseline: Current: Summary
All benchmark results (sec/op)
Threshold: >10% with p < 0.05 | Generated: 2026-06-04 12:23 UTC |
|
🤖 Claude Code Review Status: Complete No issues found. The implementation correctly addresses the startup hang scenario with proper error handling and comprehensive test coverage. Summary:
|
|
freemans13
left a comment
There was a problem hiding this comment.
Approve. Genuine bug fix: Start could hang forever on <-grpcReady when StartGRPCServer returned via any of its pre-callback error paths (bad listen address, missing cert/key, server-creation failure). The three-way select on readiness / early-startup-error / ctx.Done() resolves this comprehensively.
Strengths:
- Switching to close(grpcReady) via sync.Once is broadcast-safe and won't block the callback even after the select returns.
- grpcStartErr is buffered (cap 1) with a non-blocking send — no goroutine leak.
- Race-clean; new regression test passes under -race and fails loudly (2s timeout) rather than hanging on regression. It also verifies readyCh is still closed on the error path.
Minor (non-blocking):
- Error/cancel return paths no longer join the errgroup via g.Wait() as the original single exit did. No real leak (errgroup cancels gCtx on error return; ctx.Done propagates to the child gCtx), but a one-line comment noting this is intentional would help future readers.
- Test mixes assert.Contains with require (testing.md prefers require), though consistent with the file's existing style.
LGTM.



Summary
BlockAssembly.Startcould block forever waiting ongrpcReadyifStartGRPCServerreturned before invoking the registration callback (for example, invalid bind address or early startup failure).This change makes startup failure-aware and cancellation-aware:
grpcStartErr) inStartand wait on:ctx.Done()grpcReadywithsync.Oncefrom the registration callback.readyChvia deferred close, including failure paths.TestStartReturnsErrorWhenGRPCFailsBeforeReadyStartreturns an error instead of hangingreadyChis closed whenStartexits on errorWhy
A startup error should fail fast and surface a clear error. Previously, the service could hang indefinitely, which can wedge tests, startup orchestration, or supervisors waiting on readiness.
Test Plan
go test ./services/blockassembly -run 'TestStartReturnsErrorWhenGRPCFailsBeforeReady|TestGetBlockAssemblyTxsReturnsWhenContextCancelled'