WorkR.Triggers.AzureStorageQueues
0.3.3
dotnet add package WorkR.Triggers.AzureStorageQueues --version 0.3.3
NuGet\Install-Package WorkR.Triggers.AzureStorageQueues -Version 0.3.3
<PackageReference Include="WorkR.Triggers.AzureStorageQueues" Version="0.3.3" />
<PackageVersion Include="WorkR.Triggers.AzureStorageQueues" Version="0.3.3" />
<PackageReference Include="WorkR.Triggers.AzureStorageQueues" />
paket add WorkR.Triggers.AzureStorageQueues --version 0.3.3
#r "nuget: WorkR.Triggers.AzureStorageQueues, 0.3.3"
#:package WorkR.Triggers.AzureStorageQueues@0.3.3
#addin nuget:?package=WorkR.Triggers.AzureStorageQueues&version=0.3.3
#tool nuget:?package=WorkR.Triggers.AzureStorageQueues&version=0.3.3
WorkR.Triggers.AzureStorageQueues
Azure Storage Queue polling trigger for WorkR. Polls a queue, [optionally] deserialises messages, and passes them through a composable worker pipeline.
Installation
dotnet add package WorkR.Triggers.AzureStorageQueues
AddStorageQueueWorker
Typed messages (recommended)
Deserialise queue messages to a strongly-typed model before passing them to your worker. JSON deserialisation is used by default.
public class OrderCreatedWorker : IWorker<StorageQueueTriggerContext<OrderCreated>>
{
public async Task ExecuteAsync(
StorageQueueTriggerContext<OrderCreated> context,
CancellationToken cancellationToken)
{
var order = context.Value; // deserialized OrderCreated
await ProcessAsync(order, cancellationToken);
await context.DeleteMessageAsync(cancellationToken);
}
}
builder.Services.AddStorageQueueWorker<OrderCreated, OrderCreatedWorker>(
sp => sp.GetRequiredService<QueueServiceClient>(),
"orders");
Raw messages
Receive the raw QueueMessage without deserialisation:
public class RawWorker : IWorker<StorageQueueTriggerContext>
{
public async Task ExecuteAsync(
StorageQueueTriggerContext context,
CancellationToken cancellationToken)
{
var body = context.Value.Body.ToString(); // raw message body
await ProcessAsync(body, cancellationToken);
await context.DeleteMessageAsync(cancellationToken);
}
}
builder.Services.AddStorageQueueWorker<RawWorker>(
sp => sp.GetRequiredService<QueueServiceClient>(),
"my-queue");
StorageQueueTriggerContext
The context passed to your worker for each message.
| Member | Description |
|---|---|
Value |
The deserialized message body (T for typed, QueueMessage for raw) |
Message |
The raw QueueMessage (typed variant only) |
ExecutionId |
Unique identifier for this pipeline invocation |
OccurredAt |
When the message was received |
DeleteMessageAsync(ct) |
Deletes the message from the queue |
DeadLetterMessageAsync(ct) |
Moves the message to the poison queue (<queue-name>-poison) and deletes it from the main queue |
Worker Contract
Each message is processed on the thread pool independently of the polling loop. Workers must either return a completed task or throw — the trigger handles settlement based on the outcome and the configured options.
Message Completion
By default (AutoCompleteMessages = true) the trigger deletes the message automatically after the worker returns successfully. If the worker throws, the message is left on the queue and will become visible again after VisibilityTimeout. Once the message has been dequeued MaxDeliveryCount times it is automatically moved to the poison queue.
To take manual control, set AutoCompleteMessages = false and call DeleteMessageAsync or DeadLetterMessageAsync yourself:
builder.Services.AddStorageQueueWorker<OrderCreated, OrderCreatedWorker>(
sp => sp.GetRequiredService<QueueServiceClient>(),
"orders",
configure: options => options.AutoCompleteMessages = false);
public async Task ExecuteAsync(StorageQueueTriggerContext<OrderCreated> context, CancellationToken cancellationToken)
{
try
{
await ProcessAsync(context.Value, cancellationToken);
await context.DeleteMessageAsync(cancellationToken);
}
catch (NonRetryableException)
{
await context.DeadLetterMessageAsync(cancellationToken);
}
}
Custom Deserialiser
Supply a custom deserialiser to control how message bodies are converted to your model:
builder.Services.AddStorageQueueWorker<OrderCreated, OrderCreatedWorker>(
sp => sp.GetRequiredService<QueueServiceClient>(),
"orders",
deserializerFactory: sp => async message =>
{
var json = message.Body.ToString();
return JsonSerializer.Deserialize<OrderCreated>(json, myOptions)!;
});
The built-in JSON deserialiser can also be configured with custom JsonSerializerOptions:
deserializerFactory: _ => StorageQueueMessageDeserializers.Json<OrderCreated>(myJsonOptions)
StorageQueueTriggerOptions
| Option | Default | Description |
|---|---|---|
AutoCompleteMessages |
true |
Delete the message automatically after successful processing |
MaxDeliveryCount |
5 |
Times a message may be dequeued and fail before being automatically dead-lettered (0 to disable) |
MaxConcurrentCalls |
1 |
Maximum number of worker executions running concurrently. The polling loop applies backpressure once this limit is reached. |
MaxMessages |
1 |
Maximum messages retrieved per poll (1–32) |
VisibilityTimeout |
30s |
How long a received message remains invisible to other consumers while being processed |
PollingDelay |
Fixed 5s | Wait strategy when the queue is empty |
ErrorDelay |
Fixed 5s | Wait strategy after a transient receive error |
MaxConcurrentCalls and MaxMessages are independent. Set MaxMessages to control how many messages are fetched in one network call; set MaxConcurrentCalls to control how many workers run in parallel.
PollingDelay and ErrorDelay accept a StorageQueueDelay delegate — use StorageQueueDelayStrategy for built-in strategies:
configure: options =>
{
options.PollingDelay = StorageQueueDelayStrategy.Fixed(TimeSpan.FromSeconds(10));
options.MaxMessages = 8;
}
Full Pipeline Control
Use the builder overload to chain multiple workers or configure per-step middleware:
builder.Services.AddStorageQueueWorker<OrderCreated>(
sp => sp.GetRequiredService<QueueServiceClient>(),
"orders",
pipeline => pipeline
.AddWorker<ValidateWorker, ValidatedOrder>()
.AddWorker<PersistWorker>());
Default middleware: UseScope. Applied to the first worker in the chain only.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Azure.Storage.Queues (>= 12.20.0)
- WorkR (>= 0.3.3)
-
net8.0
- Azure.Storage.Queues (>= 12.20.0)
- WorkR (>= 0.3.3)
-
net9.0
- Azure.Storage.Queues (>= 12.20.0)
- WorkR (>= 0.3.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.3 | 47 | 5/28/2026 |
| 0.3.2-preview | 37 | 5/28/2026 |
| 0.2.1 | 97 | 5/22/2026 |
| 0.1.7-g2e3259f211 | 87 | 5/19/2026 |
| 0.1.4 | 92 | 5/22/2026 |
| 0.0.6-preview | 43 | 5/28/2026 |
| 0.0.5-preview | 37 | 5/28/2026 |