Skip to content

feature: Add option to configure custom azure servicebus processor options#140

Open
jwdb wants to merge 1 commit into
elsa-workflows:mainfrom
jwdb:feature/servicebus-processor-options
Open

feature: Add option to configure custom azure servicebus processor options#140
jwdb wants to merge 1 commit into
elsa-workflows:mainfrom
jwdb:feature/servicebus-processor-options

Conversation

@jwdb
Copy link
Copy Markdown

@jwdb jwdb commented May 4, 2026

This allows the user to configure the processor for concurrent calls, prefetching, to not autocomplete messages (but manually in the workflow for example) or reduce or increase the timeouts.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 4, 2026

Greptile Summary

This PR adds a ProcessorOptionsFactory to AzureServiceBusFeature, letting users inject a custom ServiceBusProcessorOptions (for concurrency, prefetch, timeouts, etc.) into every Worker via DI. The factory is wired through correctly using ActivatorUtilities, but there is a functional gap: the PR advertises AutoCompleteMessages = false support ("manually in the workflow") while ProcessMessageEventArgs — the object needed to settle messages — is discarded in Worker.OnMessageReceivedAsync and never surfaced to the workflow layer, so messages set to manual completion will never be settled and will dead-letter.

Confidence Score: 3/5

Not safe to merge without addressing the AutoCompleteMessages = false gap — that option will silently dead-letter all messages.

One P1 logic bug (manual message completion is architecturally impossible with the current Worker design) prevents the advertised feature from working; two P2 issues (wrong doc comment, single-instance options for all workers) are non-blocking.

Worker.cs needs ProcessMessageEventArgs to be forwarded or the AutoCompleteMessages use-case to be documented as unsupported.

Important Files Changed

Filename Overview
src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Features/AzureServiceBusFeature.cs Adds ProcessorOptionsFactory property (singleton-registered) and an incorrect XML doc comment referencing the wrong type; all workers share one ServiceBusProcessorOptions instance.
src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Services/Worker.cs Injects ServiceBusProcessorOptions from DI; but ProcessMessageEventArgs is not forwarded to workflows, making AutoCompleteMessages = false effectively broken.
src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Options/AzureServiceBusOptions.cs Adds using Azure.Messaging.ServiceBus import — trivial, no issues.

Sequence Diagram

sequenceDiagram
    participant App as Application Startup
    participant Feature as AzureServiceBusFeature
    participant DI as DI Container
    participant WM as WorkerManager
    participant W as Worker
    participant SB as ServiceBusClient

    App->>Feature: Apply()
    Feature->>DI: AddSingleton(ProcessorOptionsFactory)
    Feature->>DI: AddSingleton WorkerManager
    App->>WM: StartWorkerAsync(queueOrTopic, subscription)
    WM->>DI: ActivatorUtilities.CreateInstance Worker
    DI-->>WM: ServiceBusClient, ServiceBusProcessorOptions singleton, IServiceScopeFactory
    WM->>W: new Worker(queueOrTopic, subscription, client, processorOptions, ...)
    W->>SB: CreateProcessor(queueOrTopic, processorOptions)
    SB-->>W: ServiceBusProcessor
    W->>W: subscribe ProcessMessageAsync and ProcessErrorAsync
    W->>SB: StartProcessingAsync()
    Note over W,SB: On message received
    SB->>W: OnMessageReceivedAsync(ProcessMessageEventArgs args)
    W->>W: InvokeWorkflowsAsync(args.Message, args.CancellationToken)
    Note right of W: args with CompleteMessageAsync etc. is discarded
Loading

Comments Outside Diff (1)

  1. src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Services/Worker.cs, line 63 (link)

    P1 AutoCompleteMessages = false unusable — ProcessMessageEventArgs not forwarded

    The PR description explicitly lists "not autocomplete messages (but manually in the workflow)" as a supported scenario, but OnMessageReceivedAsync only passes args.Message and args.CancellationToken to InvokeWorkflowsAsync — the ProcessMessageEventArgs object (which exposes CompleteMessageAsync, AbandonMessageAsync, DeadLetterMessageAsync, etc.) is discarded. There are no workflow activities to complete messages either. With AutoCompleteMessages = false, every received message will be left unsettled, its lock will eventually expire, and the message will be redelivered until the dead-letter threshold is reached.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Services/Worker.cs
    Line: 63
    
    Comment:
    **`AutoCompleteMessages = false` unusable — `ProcessMessageEventArgs` not forwarded**
    
    The PR description explicitly lists "not autocomplete messages (but manually in the workflow)" as a supported scenario, but `OnMessageReceivedAsync` only passes `args.Message` and `args.CancellationToken` to `InvokeWorkflowsAsync` — the `ProcessMessageEventArgs` object (which exposes `CompleteMessageAsync`, `AbandonMessageAsync`, `DeadLetterMessageAsync`, etc.) is discarded. There are no workflow activities to complete messages either. With `AutoCompleteMessages = false`, every received message will be left unsettled, its lock will eventually expire, and the message will be redelivered until the dead-letter threshold is reached.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Services/Worker.cs:63
**`AutoCompleteMessages = false` unusable — `ProcessMessageEventArgs` not forwarded**

The PR description explicitly lists "not autocomplete messages (but manually in the workflow)" as a supported scenario, but `OnMessageReceivedAsync` only passes `args.Message` and `args.CancellationToken` to `InvokeWorkflowsAsync` — the `ProcessMessageEventArgs` object (which exposes `CompleteMessageAsync`, `AbandonMessageAsync`, `DeadLetterMessageAsync`, etc.) is discarded. There are no workflow activities to complete messages either. With `AutoCompleteMessages = false`, every received message will be left unsettled, its lock will eventually expire, and the message will be redelivered until the dead-letter threshold is reached.

### Issue 2 of 3
src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Features/AzureServiceBusFeature.cs:40-42
**Incorrect XML doc comment references wrong type**

The summary says "A delegate to create a `<see cref="AzureServiceBusOptions"/>` instance" but the property creates a `ServiceBusProcessorOptions` instance, not an `AzureServiceBusOptions`.

### Issue 3 of 3
src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Features/AzureServiceBusFeature.cs:76
**Singleton `ServiceBusProcessorOptions` shared across all workers**

`ProcessorOptionsFactory` is registered as a singleton, so every `Worker` instance — across all queues and topics — receives the exact same `ServiceBusProcessorOptions` object. If a user needs different concurrency, prefetch, or timeout settings per queue/topic, this design prevents it. Consider documenting this limitation or changing the approach (e.g., a `Func<string, string?, ServiceBusProcessorOptions>` keyed by queue/subscription).

Reviews (1): Last reviewed commit: "feature: Add option to configure custom ..." | Re-trigger Greptile

Comment on lines +40 to +42
/// A delegate to create a <see cref="AzureServiceBusOptions"/> instance.
/// </summary>
public Func<IServiceProvider, ServiceBusProcessorOptions> ProcessorOptionsFactory { get; set; } = _ => new ServiceBusProcessorOptions();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Incorrect XML doc comment references wrong type

The summary says "A delegate to create a <see cref="AzureServiceBusOptions"/> instance" but the property creates a ServiceBusProcessorOptions instance, not an AzureServiceBusOptions.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Features/AzureServiceBusFeature.cs
Line: 40-42

Comment:
**Incorrect XML doc comment references wrong type**

The summary says "A delegate to create a `<see cref="AzureServiceBusOptions"/>` instance" but the property creates a `ServiceBusProcessorOptions` instance, not an `AzureServiceBusOptions`.

How can I resolve this? If you propose a fix, please make it concise.

Services
.AddSingleton(ServiceBusAdministrationClientFactory)
.AddSingleton(ServiceBusClientFactory)
.AddSingleton(ProcessorOptionsFactory)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Singleton ServiceBusProcessorOptions shared across all workers

ProcessorOptionsFactory is registered as a singleton, so every Worker instance — across all queues and topics — receives the exact same ServiceBusProcessorOptions object. If a user needs different concurrency, prefetch, or timeout settings per queue/topic, this design prevents it. Consider documenting this limitation or changing the approach (e.g., a Func<string, string?, ServiceBusProcessorOptions> keyed by queue/subscription).

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/Features/AzureServiceBusFeature.cs
Line: 76

Comment:
**Singleton `ServiceBusProcessorOptions` shared across all workers**

`ProcessorOptionsFactory` is registered as a singleton, so every `Worker` instance — across all queues and topics — receives the exact same `ServiceBusProcessorOptions` object. If a user needs different concurrency, prefetch, or timeout settings per queue/topic, this design prevents it. Consider documenting this limitation or changing the approach (e.g., a `Func<string, string?, ServiceBusProcessorOptions>` keyed by queue/subscription).

How can I resolve this? If you propose a fix, please make it concise.

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