fix(api): correct async self-invoke payload shape so collection actually runs#265
Conversation
The async refresh path landed in PR #260 but the Lambda self-invoke payload didn't match what the receiving Lambda expects. The shipped payload was: {"event": "scheduled_recommendations"} But internal/server/handler.go::ScheduledEvent has no "event" field — it has Action, Source, DetailType, Detail. Unmarshalling that JSON gives Action="", and ParseScheduledEvent rejects every event with: unknown scheduled task action: "" Verified live in /aws/lambda/cudly-dev-426fc8af-api request 3befb380-6d46-47e1-954b-69a2b59ea90a: 16:49:40 Received unknown event (size: 37 bytes) 16:49:40 Unknown event type, treating as scheduled event 16:49:40 {"errorMessage":"failed to parse scheduled event: unknown scheduled task action: \"\""} The 37-byte event = the {"event":"scheduled_recommendations"} string exactly. The async self-invoke is firing successfully but every invocation is rejected, so the "Refreshing..." banner never clears and collection never runs — same user-visible symptom (refresh times out + no fresh data) as if the env var or IAM grant was missing. Fix: send the payload shape the dispatcher actually accepts: {"source": "aws.events", "action": "collect_recommendations"} action="collect_recommendations" maps to TaskCollectRecommendations in the ParseScheduledEvent switch. source="aws.events" makes detectLambdaEventType in internal/server/lambda.go classify the invoke consistently with EventBridge cron deliveries that already exercise this code path.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe scheduler Lambda's self-invocation payload is reformatted from ChangesScheduler Payload Update
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 4/5 reviews remaining, refill in 12 minutes. Comment |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
Summary
The async refresh path landed in #260 but the Lambda self-invoke payload doesn't match what the receiving Lambda's
ParseScheduledEventaccepts. Every async invoke is being rejected, so the user clicks Refresh, the frontend polls indefinitely, and collection never actually runs — exact same UX as the original 60s timeout.Evidence (deployed log group
/aws/lambda/cudly-dev-426fc8af-api)37 bytes = the
{"event":"scheduled_recommendations"}string exactly. The handler'sScheduledEventstruct has noeventfield — it hasAction,Source,DetailType,Detail— soActionunmarshals as""and the dispatch switch hitsdefault → unknown scheduled task action.Fix
Send the payload the dispatcher accepts:
{"source": "aws.events", "action": "collect_recommendations"}action="collect_recommendations"maps toTaskCollectRecommendationsininternal/server/handler.go::ParseScheduledEvent.source="aws.events"makesdetectLambdaEventTypeininternal/server/lambda.go(which checksSource == "aws.events" || Action != "") classify it consistently with EventBridge cron deliveries.Test plan
go build ./...succeedsgo test ./internal/api/...— 1,055 tests pass/recommendationsand confirm:collect_recommendationstask running (not the rejection error)last_collection_started_atclearsWhy this didn't surface during PR #260's CI
CI runs Go unit tests with mocked Lambda invokers, so the payload shape was never end-to-end exercised against the receiving Lambda. The mismatch only manifests in the deployed environment when the real
lambda.Invokedelivers the event back to the Lambda runtime.Closes the user-visible symptom that re-opened the parent investigation under #257.
Summary by CodeRabbit