Summary
The fan-out helper just got recover() via #669 / PR #670. Audit of all other goroutine starts surfaced 3 more fire-and-forget goroutines without recover():
| File:Line |
Purpose |
Panic blast radius |
internal/auth/service_apikeys.go:279 |
Async UpdateLastUsed after API-key auth |
crashes Lambda mid-request (any path including in-flight purchase) |
internal/api/db_rate_limiter.go:137 |
Async cleanup() of expired rate-limit entries |
crashes Lambda mid-request |
internal/api/handler_accounts.go:811 |
GCP ts.Token() with timeout channel |
crashes Lambda on account-test requests |
Each is LOW likelihood (small DB UPDATE / cleanup / a single library call), but a panic kills the entire Lambda process. Cheap insurance.
Pattern to apply (matches existing internal/api/ri_utilization_cache.go:153):
defer func() {
if r := recover(); r != nil {
logging.Warnf("<context>: background goroutine panic: %v", r)
}
}()
Acceptance criteria
Cross-references
Summary
The fan-out helper just got
recover()via #669 / PR #670. Audit of all other goroutine starts surfaced 3 more fire-and-forget goroutines without recover():internal/auth/service_apikeys.go:279UpdateLastUsedafter API-key authinternal/api/db_rate_limiter.go:137cleanup()of expired rate-limit entriesinternal/api/handler_accounts.go:811ts.Token()with timeout channelEach is LOW likelihood (small DB UPDATE / cleanup / a single library call), but a panic kills the entire Lambda process. Cheap insurance.
Pattern to apply (matches existing
internal/api/ri_utilization_cache.go:153):Acceptance criteria
logging.Warnf(these are non-critical paths; Warn is right level)ri_utilization_cache_test.gois sufficient as a precedent)Cross-references