Skip to content

feat(webhooks): add dispatch queue publisher (NAN-5339) 1/5#5955

Merged
agusayerza merged 1 commit into
masterfrom
agus/NAN-5339/dispatch-queue-publisher
Apr 30, 2026
Merged

feat(webhooks): add dispatch queue publisher (NAN-5339) 1/5#5955
agusayerza merged 1 commit into
masterfrom
agus/NAN-5339/dispatch-queue-publisher

Conversation

@agusayerza
Copy link
Copy Markdown
Contributor

  • WebhookDispatchMessage shared type in @nangohq/types
  • DispatchQueuePublisher in server package: batched SendMessageBatch, parallel batches, one inline retry for failed entries, partial-failure emits metric + log
  • New WEBHOOK_DISPATCH_* metric types in @nangohq/utils
  • Adds @aws-sdk/client-sqs depedency to server

No call sites yet, wired up in NAN-5340.

@linear
Copy link
Copy Markdown

linear Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 9 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

@agusayerza agusayerza requested a review from a team April 27, 2026 14:40
@agusayerza agusayerza changed the title feat(webhooks): add dispatch queue publisher abstraction (NAN-5339) feat(webhooks): add dispatch queue publisher (NAN-5339) Apr 27, 2026
@agusayerza agusayerza marked this pull request as ready for review April 27, 2026 14:46
Comment thread packages/server/lib/webhook/dispatch-queue/publisher.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 74bcc1255f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/types/lib/webhooks/dispatch.ts
const failedIds = (response.Failed ?? []).map((f) => f.Id).filter((id): id is string => typeof id === 'string');
return { failedIds };
} catch (err) {
logger.error(`SendMessageBatchCommand threw`, { error: err });
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.

Intetional log here as we don't have per-batch tracing

@agusayerza agusayerza force-pushed the agus/NAN-5339/dispatch-queue-publisher branch from 74bcc12 to 269273c Compare April 27, 2026 16:16
return {
Id: indexToEntryId(index),
MessageBody: JSON.stringify(message),
MessageGroupId: messageGroupId
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

no MessageDeduplicationId

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.

We are using a standard SQS queue with fair-queue behavior via MessageGroupId, not a FIFO queue. Unfortunately the caveat is that fair-queues do not support MessageDeduplicationId. We will be using the task name to dedupe on the orchestrator. I'm open to using a FIFO queue with MessageDeduplicationId but we lose the fairness across tenants. Even then orchestrator would still need deduping transport retries. (FIFO guarantees at-least-once delivery)

/**
* Publish a list of dispatch messages in batches. Batches are fired in parallel up to
* `publishConcurrency`; failed entries within a batch are retried once inline. Any
* entries still failing after the retry are counted as `failed`. Never throws — the
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Never throws is contradicted by L112

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.

Yeah, fixing it. I meant never throws on regular SQS operations.


if (enqueued > 0) {
metrics.increment(metrics.Types.WEBHOOK_DISPATCH_MESSAGES_ENQUEUED, enqueued, { provider });
metrics.increment(metrics.Types.WEBHOOK_DISPATCH_PUBLISH_SUCCESS, enqueued, { provider });
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need both? We are counting the same things twice

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.

Agreed, enqueued ended up being redundant here and also reads more like queue depth, so I removed it and kept publish.success / publish.failure

tracerMocks.dogstatsd.decrement.mockClear();
tracerMocks.dogstatsd.gauge.mockClear();
tracerMocks.dogstatsd.histogram.mockClear();
tracerMocks.dogstatsd.distribution.mockClear();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

isn't restoreAllMocks already cleaning up the spies?

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.

Most of these are hoisted vi.fn() mocks, not vi.spyOns, and restoreAllMocks() does not clear or reset the history of vi.fn()

@agusayerza agusayerza requested review from a team and TBonnin April 27, 2026 20:02
@agusayerza agusayerza force-pushed the agus/NAN-5339/dispatch-queue-publisher branch 3 times, most recently from 907fa9e to 5fb9cd8 Compare April 28, 2026 02:22
@agusayerza agusayerza changed the base branch from agus/NAN-5338/ingress-request-id to master April 28, 2026 12:32
}
this.batchSize = Math.min(configuredBatchSize, SQS_BATCH_MAX_ENTRIES);

const configuredPublishConcurrency = props.publishConcurrency ?? SQS_BATCH_MAX_ENTRIES;
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.

Why are we using a constant for batching as a default for concurrency?

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.

Missed this, originally I had set it to the same value and forgot to split into new const

@@ -67,6 +67,16 @@ export enum Types {
WEBHOOK_ASYNC_ACTION_FAILED = 'nango.webhook.async_action.failed',
WEBHOOK_INCOMING_PAYLOAD_SIZE_BYTES = 'nango.webhook.incoming.payloadSizeBytes',

WEBHOOK_DISPATCH_PUBLISH_SUCCESS = 'nango.webhook.dispatch_queue.publish.success',
WEBHOOK_DISPATCH_PUBLISH_FAILURE = 'nango.webhook.dispatch_queue.publish.failure',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I imagine the following metrics are declared for future use?

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.

Correct

@agusayerza agusayerza changed the title feat(webhooks): add dispatch queue publisher (NAN-5339) feat(webhooks): add dispatch queue publisher (NAN-5339) 1/4 Apr 29, 2026
@agusayerza agusayerza force-pushed the agus/NAN-5339/dispatch-queue-publisher branch from 2e1ff55 to b4f5512 Compare April 29, 2026 18:28
@agusayerza agusayerza changed the title feat(webhooks): add dispatch queue publisher (NAN-5339) 1/4 feat(webhooks): add dispatch queue publisher (NAN-5339) 1/5 Apr 29, 2026
Introduces a DispatchQueuePublisher abstraction for publishing webhook execution messages to SQS. Uses activity log ID as the message identifier. Adds tracing and a shared webhook concurrency helper.
@agusayerza agusayerza force-pushed the agus/NAN-5339/dispatch-queue-publisher branch from b4f5512 to ec71242 Compare April 30, 2026 14:45
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec71242da9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

return {
Id: indexToEntryId(index),
MessageBody: JSON.stringify(message),
MessageGroupId: messageGroupId
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate FIFO requirements before setting SQS group fields

toEntry always sends MessageGroupId but never sets MessageDeduplicationId, which only works for a FIFO queue that already has content-based dedup enabled. In environments where the queue is standard, or FIFO without content-based deduplication, SendMessageBatch will reject every entry and this publisher will return all messages as failed, causing webhook dispatches to be dropped instead of queued. Please either enforce/validate the queue mode at construction time or include a deterministic deduplication ID (for example from taskName) when publishing.

Useful? React with 👍 / 👎.

@agusayerza agusayerza added this pull request to the merge queue Apr 30, 2026
Merged via the queue into master with commit 5e2da9b Apr 30, 2026
23 checks passed
@agusayerza agusayerza deleted the agus/NAN-5339/dispatch-queue-publisher branch April 30, 2026 16:00
hassan254-prog pushed a commit that referenced this pull request May 1, 2026
- WebhookDispatchMessage shared type in `@nangohq/types`
- DispatchQueuePublisher in server package: batched SendMessageBatch,
parallel batches, one inline retry for failed entries, partial-failure
emits metric + log
- New WEBHOOK_DISPATCH_* metric types in `@nangohq/utils`
- Adds `@aws-sdk/client-sqs` depedency to server

No call sites yet, wired up in NAN-5340.

<!-- Describe the problem and your solution --> 

<!-- Issue ticket number and link (if applicable) -->

<!-- Testing instructions (skip if just adding/editing providers) -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants