Skip to content

[Linkedin Conversions] Add multistatus in linkedin conversions' stream conversion event#3745

Draft
harsh-joshi99 wants to merge 1 commit intomainfrom
fix/linkedin-conversions-batch-poisoning
Draft

[Linkedin Conversions] Add multistatus in linkedin conversions' stream conversion event#3745
harsh-joshi99 wants to merge 1 commit intomainfrom
fix/linkedin-conversions-batch-poisoning

Conversation

@harsh-joshi99
Copy link
Copy Markdown
Contributor

Testing

Include any additional information about the testing you have completed to
ensure your changes behave as expected. For a speedy review, please check
any of the tasks you completed below during your testing.

  • 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
  • [Segmenters] [If applicable for this change] Tested for regression with Hadron.

Security Review

Please ensure sensitive data is properly protected in your integration.

  • Reviewed all field definitions for sensitive data (API keys, tokens, passwords, client secrets) and confirmed they use type: 'password'

New Destination Checklist

  • Extracted all action API versions to verioning-info.ts file. example

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds spec-v2 MultiStatus support to the LinkedIn Conversions streamConversion batched pathway so invalid events can be failed individually while valid events in the same batch are still sent.

Changes:

  • Update LinkedInConversions.batchConversionAdd to build and return a MultiStatusResponse, filtering invalid payloads and mapping responses back to original batch indices.
  • Remove legacy try/catch wrapping in the action’s performBatch now that the API client returns a MultiStatus response.
  • Add unit tests covering mixed-validity batches, all-invalid batches (no outbound call), index mapping, and 401 handling.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/destination-actions/src/destinations/linkedin-conversions/streamConversion/index.ts Switch batched execution to directly return the API client’s MultiStatusResponse.
packages/destination-actions/src/destinations/linkedin-conversions/api/index.ts Implement MultiStatus construction, validation filtering, and per-index success/error response mapping.
packages/destination-actions/src/destinations/linkedin-conversions/streamConversion/tests/index.test.ts Add coverage for multistatus behavior across validation errors, no-op batches, 401 throws, and index mapping.

Comment on lines +524 to +543
} catch (error) {
if (error instanceof HTTPError) {
const status = error.response.status

// 401 means the OAuth token is expired — re-throw so the platform triggers a token refresh
if (status === 401) {
throw new InvalidAuthenticationError(
'LinkedIn OAuth token is expired or invalid. Please re-authenticate.',
ErrorCodes.INVALID_AUTHENTICATION
)
}

// For all other API errors, mark every valid event as failed with the actual status
validResponseIndices.forEach((originalIndex, filteredIndex) => {
multiStatusResponse.setErrorResponseAtIndex(originalIndex, {
status,
errormessage: error.message,
sent: validElements[filteredIndex] as unknown as JSONLikeObject
})
})
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the LinkedIn batch API call fails with retryable statuses (e.g., 408/423/429 and most 5xx), returning a MultiStatusResponse marks events as permanently failed and bypasses the retry behavior previously implemented via handleRequestError (which classified these as retryable). Consider throwing a RetryableError (or otherwise surfacing a retryable failure) for these whole-batch transport/API failures so events are retried instead of dropped.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot based on this feedback, prior to this change, was the handleRequestError being called for failures coming from the request, seeing as we do not await.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — handleRequestError was not being called for HTTP request failures in the original code. Because batchConversionAdd was returned without await, the surrounding try/catch only captured synchronous errors. Any async errors from the HTTP request (5xx, 429, etc.) would propagate as unhandled promise rejections and bypass handleRequestError entirely.

So the retryable-error concern raised by the reviewer is a net-new consideration rather than a regression from the original behavior. The original code was already broken for those cases.

Comment on lines +536 to +542
// For all other API errors, mark every valid event as failed with the actual status
validResponseIndices.forEach((originalIndex, filteredIndex) => {
multiStatusResponse.setErrorResponseAtIndex(originalIndex, {
status,
errormessage: error.message,
sent: validElements[filteredIndex] as unknown as JSONLikeObject
})
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTPError.message is derived from response.statusText (often generic/empty) and won't include LinkedIn's error payload. To make multistatus error details actionable, prefer populating errormessage (and optionally body) from error.response.data / error.response.content when available.

Copilot uses AI. Check for mistakes.
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 83.87097% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.92%. Comparing base (f3ebd4f) to head (0392c13).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...src/destinations/linkedin-conversions/api/index.ts 83.33% 1 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3745      +/-   ##
==========================================
- Coverage   81.07%   80.92%   -0.15%     
==========================================
  Files        1655     1347     -308     
  Lines       32088    25067    -7021     
  Branches     7090     5202    -1888     
==========================================
- Hits        26014    20285    -5729     
+ Misses       5101     3835    -1266     
+ Partials      973      947      -26     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants