Skip to content

feat(webhook): allow multiple webhook URLs per instance (fan-out) - #138

Open
samuelpc7 wants to merge 1 commit into
evolution-foundation:mainfrom
samuelpc7:feat/multiple-webhooks
Open

feat(webhook): allow multiple webhook URLs per instance (fan-out)#138
samuelpc7 wants to merge 1 commit into
evolution-foundation:mainfrom
samuelpc7:feat/multiple-webhooks

Conversation

@samuelpc7

@samuelpc7 samuelpc7 commented Jul 28, 2026

Copy link
Copy Markdown

Description

The instance Webhook field can now hold multiple URLs. The producer delivers the
SAME event request to every address (each with its own retry). Accepted formats:
newline / comma / semicolon separated, or a JSON array. Duplicates, empty entries
and the "disabled" marker are ignored.

No schema change: the Webhook column stays a string; only
pkg/events/webhook/webhook_producer.go was touched (new splitWebhookURLs
helper). Fully backward compatible — a single URL behaves exactly as before. The
global webhook (config.WebhookUrl) keeps being sent in parallel.

Related Issue

N/A

Type of Change

  • New feature (non-breaking change which adds functionality)

Testing

  • Manual testing completed
  • Functionality verified in development environment
  • No breaking changes introduced

Screenshots (if applicable)

N/A — backend only.

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have tested my changes thoroughly
  • Any dependent changes have been merged and published

Additional Notes

Single-file change. Produce now fans the same payload out to every URL returned
by splitWebhookURLs, instead of a single webhookUrl.

Summary by Sourcery

New Features:

  • Allow an instance webhook configuration to specify multiple URLs, each receiving the same event payload with independent retries.

@sourcery-ai

sourcery-ai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Reviewer's Guide

Enables fan-out of instance webhooks by parsing the existing single string field into multiple URLs (supporting several input formats) and sending the same payload concurrently to each URL while preserving existing global webhook behavior.

Sequence diagram for webhook fan-out in Produce

sequenceDiagram
    participant Producer as webhookProducer
    participant GlobalWebhook as p.url
    participant Splitter as splitWebhookURLs
    participant InstanceWebhook as webhookUrl

    Producer->>GlobalWebhook: sendWebhookWithRetry(p.url, payload, ...)
    activate GlobalWebhook
    deactivate GlobalWebhook

    Producer->>Splitter: splitWebhookURLs(webhookUrl)
    activate Splitter
    Splitter-->>Producer: []string urls
    deactivate Splitter

    loop for each url in urls
        Producer->>InstanceWebhook: sendWebhookWithRetry(url, payload, ...)
    end
Loading

File-Level Changes

Change Details Files
Produce now fans out instance webhooks to multiple URLs instead of a single destination.
  • Replaced single call to sendWebhookWithRetry for the instance webhook with a loop over parsed URLs from splitWebhookURLs.
  • Preserved existing behavior for the global config webhook URL, which is still sent in parallel to instance webhooks.
  • Ensured each target URL is invoked in its own goroutine while keeping retry parameters unchanged.
pkg/events/webhook/webhook_producer.go
Added splitWebhookURLs helper to parse and normalize the instance Webhook string into distinct URLs.
  • Introduced JSON array parsing path for webhook strings starting with '[' using encoding/json.
  • Added fallback parsing that splits on newline, carriage return, comma, or semicolon characters.
  • Normalized and filtered entries by trimming whitespace, ignoring empty values and the literal "disabled", and de-duplicating URLs using a map.
  • Handled empty and "disabled"-only raw values by returning nil for no URLs.
pkg/events/webhook/webhook_producer.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Fan-out currently spawns an unbounded goroutine per URL with full retry logic; consider adding some form of concurrency limiting or a worker pool so a misconfigured instance with many URLs cannot exhaust resources.
  • The special "disabled" marker is hard-coded and case-sensitive in multiple places in splitWebhookURLs; consider centralizing this into a constant and/or normalizing case so configuration is less brittle and easier to change later.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Fan-out currently spawns an unbounded goroutine per URL with full retry logic; consider adding some form of concurrency limiting or a worker pool so a misconfigured instance with many URLs cannot exhaust resources.
- The special "disabled" marker is hard-coded and case-sensitive in multiple places in splitWebhookURLs; consider centralizing this into a constant and/or normalizing case so configuration is less brittle and easier to change later.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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.

1 participant