Parse Customer.io Track API batch multi-status responses#3657
Parse Customer.io Track API batch multi-status responses#3657jcpsimmons wants to merge 3 commits intosegmentio:mainfrom
Conversation
|
This draft is 1 of 3 upstream Customer.io PRs for CDP-4750. Scope here: only Track API batch multi-status parsing in Not in this PR:
Companion drafts:
This supersedes the Track API parsing portion of the older combined draft #3654. |
|
Hi @joe-ayoub-segment could I please have review on this and the other two PRs 🙏 |
joe-ayoub-segment
left a comment
There was a problem hiding this comment.
Hi @jcpsimmons,
Thanks for raising the PR for this change. It will really help customers with observability.
I left some comments for you to look at.
I didn't review all of the PR as i found it difficult to follow. Adding the types (see comments) will help me better understand the logic.
One final thing - please add proof of testing to the PR description.
- show batch payloads being delivered
- show error responses being returned correctly
Let me know if you have any questions or would like assistance.
best regards,
Joe
| if (response?.status === 207 && responseBody) { | ||
| const parsedResults = parseTrackApiMultiStatusResponse(responseBody, batch.length) | ||
| if (parsedResults) { | ||
| return parsedResults | ||
| } | ||
| } | ||
|
|
||
| if (response?.status === 200 && responseBody) { | ||
| const parsedResults = parseTrackApiMultiStatusResponse(responseBody, batch.length) | ||
| if (parsedResults) { | ||
| return parsedResults | ||
| } | ||
| } |
There was a problem hiding this comment.
nit: Can we reduce the redundant code here?
There was a problem hiding this comment.
Done, collapsed the two blocks into a single OR condition.
| const batch = options.map((opts) => buildPayload(opts)) | ||
|
|
||
| return request(`${trackApiEndpoint(settings)}/api/${CUSTOMERIO_TRACK_API_VERSION}/batch`, { | ||
| const response = await request(`${trackApiEndpoint(settings)}/api/${CUSTOMERIO_TRACK_API_VERSION}/batch`, { |
There was a problem hiding this comment.
Can we add an expected response type to this?
For example:
const response = await request<CustomerIOBatchResponse>(`${trackApiEndpoint(settings)}/api/${CUSTOMERIO_TRACK_API_VERSION}/batch`, {
method: 'POST',
json { batch }
})
There was a problem hiding this comment.
Also, consider wrapping this request in a try catch so that you can properly populate errors in the multistatusResponse when the entire payload fails.
try {
const response = await request(${trackApiEndpoint(settings)}/api/${CUSTOMERIO_TRACK_API_VERSION}/batch, {
method: 'POST',
json { batch }
})
}
catch(err) {
const error as CustomerIOErrorResponse
// for each payload in the batch, do setErrorResponseAtIndex
}
There was a problem hiding this comment.
Added. Renamed TrackApiResponse to CustomerIOBatchResponse and passed it as the generic: request<CustomerIOBatchResponse>(...). Also wrapped the whole thing in a try/catch per your other comment so failed requests populate every index with the error details.
There was a problem hiding this comment.
Added. The catch block extracts the status and message from the error, then iterates over every item in the batch and calls setErrorResponseAtIndex with the original payload and sent JSON. If the whole request blows up, every item in the multi-status response reflects the failure.
| } | ||
| }) | ||
|
|
||
| const responseBody = getResponseBody(response) |
There was a problem hiding this comment.
Can we add a type to this too please?
There was a problem hiding this comment.
Covered by the same rename. getResponseBody now returns CustomerIOBatchResponse | string | undefined and that flows through to parseTrackApiMultiStatusResponse.
| const error = errorMap.get(i) | ||
|
|
||
| if (!error) { | ||
| multiStatusResponse.setSuccessResponseAtIndex(i, { |
There was a problem hiding this comment.
The contents of each multiStatusResponse item is passed to the UI for observability purposes.
So if possible we should populate body and sent values correctly:
msResponse.setSuccessResponseAtIndex(index, {
status: 200,
body: // this should be the original payload object sent to the perform function,
sent: // this should be the actual JSON which was posted to your platform
})
There was a problem hiding this comment.
Good call. Threaded the original options array and the built batch array through to parseTrackApiErrors. Success responses now get body: options[i].payload (original payload from perform) and sent: batch[i] (the transformed JSON we posted).
| continue | ||
| } | ||
|
|
||
| multiStatusResponse.setErrorResponseAtIndex(i, { |
There was a problem hiding this comment.
Similarly to successful responses, we should try and populate error responses with correct details.
msResponse.setErrorResponseAtIndex(index, {
status: 400,
errortype,
errormessage,
body: // this should be the original payload object sent to the perform function,
sent: // this should be the actual JSON which was posted to your platform
})
There was a problem hiding this comment.
Same fix, error responses now also get body: options[i].payload and sent: batch[i].
| } | ||
| } | ||
|
|
||
| function getResponseBody(response: RequestResponse): unknown { |
There was a problem hiding this comment.
Please define a proper response type for this function.
There was a problem hiding this comment.
Done. Returns CustomerIOBatchResponse | string | undefined now.
… try/catch - Collapse duplicate 200/207 status blocks into single OR condition - Rename TrackApiResponse to CustomerIOBatchResponse and add as request generic - Add return type to getResponseBody - Thread original payloads and built batch through to populate body/sent in multi-status responses - Wrap batch request in try/catch to handle full payload failures
2244302 to
8be62ad
Compare
|
HI @joe-ayoub-segment thank you for that feedback - I've addressed could I please have a re-review? |
Parses Customer.io Track API batch responses into per-item
MultiStatusResponseresults so Segment can surface partial failures correctly.Testing
Verified locally under Node
22.13.1:TZ=UTC yarn cloud test --testPathPattern=src/destinations/customerio/__tests__/utils.test.ts✅./bin/run serve --destination=customerio -nboots successfully and exposes the Customer.io action routes ✅End-to-end testing using the local server was completed ✅
Added unit tests for new functionality
Tested end-to-end using the local server
[If destination is already live] Tested for backward compatibility of destination. Note: New required fields are a breaking change.
[Segmenters] Tested in the staging environment
[If applicable for this change] Tested for regression with Hadron.
Security Review
No field definitions or credential handling were changed in this PR.
passwordNew Destination Checklist
Not applicable.
verioning-info.tsfile. example