Repository navigation
fix(alb,tsm): skip timeseries unmarshaling for non-2xx gather responses - #1212
Conversation
When an ALB TSM pool member returns a non-2xx status code (e.g., 400 Bad Request with error JSON), TSM was attempting to unmarshal the error payload as a timeseries dataset via prepareGatherContribution. This caused spurious decode failure warnings and prevented clean error propagation. This change guards prepareGatherContribution with a 2xx check in both serveStandard and collectPlanResult, ensuring non-2xx responses are treated as failed member contributions without attempting timeseries unmarshaling. Signed-off-by: thinker0 <thinker0@gmail.com> Co-authored-by: Gemini <noreply@google.com>
e84db31 to
840fffb
Compare
There was a problem hiding this comment.
@thinker0 thanks for this. I have done a review and have 2 findings:
- when all fanout requests return >=400, this change causes a Trickster-generated empty 502 error from the internal responder, since the error body remains a nil []byte at time_series_merge.go L584. Trickster must return the same error body/code as one of the fanout requests when all of them fail. For example, if all fanouts return a 400 due to an invalid query syntax, then Trickster must do so as well. If all fanouts return errors but they are different (some 400's, some 502's, some 504's, etc.) then it might make sense to return the lowest error since a 4xx is usually due to user error and we should tell them what was wrong with the original request.
- The spies at time_series_merge_test.go L313 and L357 do not actually work to test for regressions, because they use the parent resources, while a fanout creates fresh resources. Since the spy stubs don't setup
TSUnmarshalerorTimeRangeQueryboth tests would actually pass as-is regardless of any changes in time_series_merge.go. Make sure the regression tests actually prove the fixed regressions they claim to prove.
… fail Address PR trickstercache#1212 review feedback: - Propagate error status code, headers, and body when all fanouts fail (no 2xx members), preferring lowest 4xx user error over 5xx. - Avoid attempting accumulator timeseries merge on non-2xx responses. - Attach spy TSUnmarshaler directly to child fanout resources in unit tests to reliably verify that timeseries decoding is skipped. - Add regression test for mixed error responses (400 vs 502/504). Signed-off-by: thinker0 <thinker0@gmail.com> Co-authored-by: Gemini <noreply@google.com>
|
@jranson Thank you for the thoughtful review and catching these edge cases! I have addressed both findings in commit 1415655:
|
|
Here's the linter failure: |
… fail Address PR trickstercache#1212 review feedback: - Propagate error status code, headers, and body when all fanouts fail (no 2xx members), preferring lowest 4xx user error over 5xx. - Avoid attempting accumulator timeseries merge on non-2xx responses. - Attach spy TSUnmarshaler directly to child fanout resources in unit tests to reliably verify that timeseries decoding is skipped. - Add regression test for mixed error responses (400 vs 502/504). Signed-off-by: thinker0 <thinker0@gmail.com> Co-authored-by: Gemini <noreply@google.com>
1415655 to
081b0b1
Compare
|
Fixed the revive linter failure in commit |
| sc = rsc2.Response.StatusCode | ||
| var rawBody []byte | ||
| if fr.Capture != nil && len(fr.Capture.Body()) > 0 { | ||
| rawBody = bytes.Clone(fr.Capture.Body()) |
There was a problem hiding this comment.
it looks like rawBody and rawHeader below are being created from Clones unconditionally, even though that data is only used for error responses. Can you gate these Clones behind an error response check, so healthy responses don't get cloned?
… fail Address PR trickstercache#1212 review feedback: - Propagate error status code, headers, and body in both serveStandard and serveMultiVariantPlan when all fanouts/variants fail (no 2xx members). - Gate rawBody and rawHeader clones behind !is2xx check in serveStandard and collectPlanResult to avoid allocating memory for healthy responses. - Attach spy TSUnmarshaler directly to child fanout resources in unit tests to reliably verify that timeseries decoding is skipped. - Add regression tests for mixed error responses (400 vs 502/504) and all-variant failure in serveMultiVariantPlan. Signed-off-by: thinker0 <thinker0@gmail.com> Co-authored-by: Gemini <noreply@google.com>
081b0b1 to
23cb417
Compare
|
@jranson Thank you for the insightful review! I have updated the PR with both requested changes:
|
Description
When an ALB TSM pool member returns a non-2xx status code (e.g.,
400 Bad Requestwith an error JSON payload), TSM was unconditionally callingprepareGatherContributionto unmarshal the response body as a timeseries dataset. This caused spurious decode failure warnings in logs and hindered clean error propagation.Root Cause
In
pkg/backends/alb/mech/tsm/time_series_merge.go(andmerge_plan.go),prepareGatherContributionwas invoked without checking whether the member's captured response was a successful2xxresponse:400 Bad Requestwith{"status":"error","errorType":"bad_data",...}),prepareGatherContributionpassed the non-timeseries payload intorsc.TSUnmarshaler.WARN tsm gather timeseries decode failure member=N error="..."time_series_merge.go, the status codescwas calculated after the contribution processing block rather than before it.Solution
scprior to contribution processing and guardprepareGatherContributionwith anis2xxcheck (sc >= 200 && sc < 300) in bothserveStandard(time_series_merge.go) andcollectPlanResult(merge_plan.go).failed: truewhile preserving its original status code and headers for proper aggregation byaggregateStatusandpickWinner.Test Coverage
Added two unit tests in
pkg/backends/alb/mech/tsm/time_series_merge_test.go:TestTSMNon2xxMemberDoesNotAttemptDecode: Verifies that a 400 Bad Request member response does not triggerTSUnmarshaler, and partial failure with a 2xx member aggregates to200 OKwithstatus=phit.TestTSMAllMembers400DoesNotAttemptDecode: Verifies that when all members return 400 Bad Request,TSUnmarshaleris not invoked and the 400 status is properly propagated.All existing unit tests in
pkg/backends/alb/mech/tsm/...andpkg/proxy/engines/...pass.Type of Change
AI Disclosure