fix(types): add timeout per request in retrieve helper - #2726
Conversation
|
The latest Buf updates on your PR. Results from workflow CI and Release / buf-check (pull_request).
|
Code Review: Timeout Per Request in Retrieve HelperSummaryThis PR addresses an important timeout issue where downloading many blobs would timeout after 10 seconds total. The fix properly applies timeout per individual request rather than for all requests combined. ✅ Strengths
🔍 Code Quality Observations1. Context Cancellation Pattern (types/da.go:184-186)getBlobsCtx, cancel := context.WithTimeout(ctx, requestTimeout)
batchBlobs, err := da.Get(getBlobsCtx, idsResult.IDs[i:end], namespace)
cancel()✅ Good: Using immediate
2. Timeout Value (da_retriever.go:23)const defaultDATimeout = 10 * time.Second💭 Consider: 10 seconds per request seems reasonable, but:
Suggestion: Consider making this configurable via config or adding a comment explaining the rationale for 10s. 3. Test Timeout Values (da_test.go:265, 291)result := types.RetrieveWithHelpers(context.Background(), mockDA, logger, dataLayerHeight, encodedNamespace.Bytes(), 1*time.Millisecond)✅ Good: Using 1ms ensures tests run quickly and reliably trigger timeouts. 🐛 Potential IssuesNo Critical Bugs FoundThe implementation correctly handles:
🚀 Performance Considerations
🔒 Security Considerations✅ No security concerns identified The changes:
📝 Additional Suggestions
logger.Debug().Int("total_ids", len(idsResult.IDs)).Int("batches", (len(idsResult.IDs)+batchSize-1)/batchSize).Msg("Starting blob retrieval")
type DARetrieverConfig struct {
GetIDsTimeout time.Duration
GetBlobsTimeout time.Duration
BatchSize int
}
✅ RecommendationsApprove with minor suggestions The PR successfully fixes the timeout issue and is well-tested. The implementation is clean and follows Go best practices. Before merging:
Nice to have (for future PRs):
📚 References
Great work fixing this issue! 🎉 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2726 +/- ##
=======================================
Coverage 66.35% 66.36%
=======================================
Files 77 77
Lines 7901 7902 +1
=======================================
+ Hits 5243 5244 +1
Misses 2173 2173
Partials 485 485
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code Review: PR #2726 - Add timeout per request in retrieve helperSummaryThis PR fixes a timeout issue where downloading many blobs would timeout after 10 seconds total. The fix applies a 10-second timeout per request (GetIDs and Get operations) instead of a single timeout for all requests combined. ✅ Strengths
🔍 Issues and Concerns1. Critical: Unused Constant in da_retriever.goSeverity: High The old constant // Line 22 in da_retriever.go (current file)
const dAFetcherTimeout = 10 * time.Second // ❌ UNUSED after changesMeanwhile, the PR adds Recommendation:
2. Design Issue: Timeout Removed from Top-Level OperationSeverity: Medium The original code had a timeout for the entire // BEFORE (lines 67-68 in old code)
ctx, cancel := context.WithTimeout(ctx, dAFetcherTimeout)
defer cancel()This has been completely removed. Now there's only per-request timeouts in Problem: If you're retrieving from two namespaces (header + data), and each namespace has multiple batches, the total time is unbounded. For example:
Recommendation: Consider adding back an overall timeout for 3. Potential Resource Leak in Get LoopSeverity: Low-Medium In for i := 0; i < len(idsResult.IDs); i += batchSize {
getBlobsCtx, cancel := context.WithTimeout(ctx, requestTimeout)
batchBlobs, err := da.Get(getBlobsCtx, idsResult.IDs[i:end], namespace)
cancel() // ✅ Good - called immediately
// ...
}This is correct, but it's slightly unconventional. The more idiomatic Go pattern would be: for i := 0; i < len(idsResult.IDs); i += batchSize {
func() {
getBlobsCtx, cancel := context.WithTimeout(ctx, requestTimeout)
defer cancel()
batchBlobs, err := da.Get(getBlobsCtx, idsResult.IDs[i:end], namespace)
// ...
}()
}However, your current approach is valid and actually clearer in this case. No change needed, but be aware some linters might flag it. 4. Missing Error Context in TestsSeverity: Low The new timeout tests check for "context deadline exceeded" in error messages: assert.Contains(t, result.Message, "context deadline exceeded")However, the actual error from
The tests should verify the full message format for clarity. Consider: assert.Contains(t, result.Message, "failed to get IDs")
assert.Contains(t, result.Message, "context deadline exceeded")5. Documentation Could Be ClearerSeverity: Low The comment for // requestTimeout defines the timeout for the each retrieval request.Minor grammar issue: "the each" → "each". Better version: // requestTimeout defines the timeout for each individual retrieval request (GetIDs and Get operations).🎯 Performance Considerations✅ Positive: The per-request timeout approach is better for scenarios with many blobs, as it allows each operation to have adequate time.
This is a 6x increase from the previous 10s limit. This might be intentional, but should be documented or made configurable. 🔒 Security Considerations✅ No security concerns identified. The timeout changes don't introduce vulnerabilities. ✅ Proper context handling prevents goroutine leaks. 📋 Recommendations SummaryMust Fix:
Should Consider: Optional: ✅ Final VerdictThe core fix is sound and addresses a real issue. With the suggested fixes (especially removing the unused constant), this PR will be in good shape. The removal of the overall operation timeout should be explicitly discussed with the team to ensure it aligns with the intended behavior. Great work on the comprehensive test coverage! 🎉 |
Overview
Downloading many blobs would timeout after 10s. We should timeout per request and for all requests.