Kanject.Core.Queue

SQS wrapper with typed messages, idempotency keys, retry policies, and an attribute-bound handler model. Dead-letter queues are provisioned alongside main queues on first deploy.

Install

bash
dotnet add package Kanject.Core.Queue

Register

csharp
using Kanject.Core.Queue.Provider.Sqs.Extensions;

builder.Services.AddSqsQueue<OrderJob>(options =>
{
    options.QueueName       = $"{appSettings.Stage}-order-jobs";
    options.AwsRegion       = appSettings.AwsRegion;
    options.MaxRetries      = 5;
    options.VisibilityTimeout = TimeSpan.FromMinutes(2);
    options.UseDeadLetter   = true;       // sibling DLQ provisioned automatically
});

Send

csharp
public record OrderJob(Guid OrderId, string Action);

public class CheckoutController(IQueue<OrderJob> jobs)
{
    [HttpPost("orders/{id:guid}/ship")]
    public async Task<IActionResult> ShipAsync(Guid id)
    {
        await jobs.SendAsync(
            message: new OrderJob(id, "ship"),
            idempotencyKey: $"ship:{id}");      // dedupes within the SQS dedup window

        return Accepted();
    }
}

Handle

csharp
[QueueHandler(typeof(OrderJob))]
public class OrderJobHandler(IShippingService shipping) : IQueueHandler<OrderJob>
{
    public async Task HandleAsync(OrderJob job, CancellationToken ct)
    {
        if (job.Action == "ship")
            await shipping.DispatchAsync(job.OrderId, ct);

        // Throwing requeues the message; if MaxRetries is exhausted it goes to DLQ.
    }
}

[QueueHandler] registers the type as a Lambda subscriber on deploy. The CLI wires the SQS event source — you write the handler.

What ships with it

  • Typed IQueue<T> per message type — JSON serialized end-to-end
  • Idempotency key support via SQS deduplication window
  • Configurable retry policy + automatic DLQ provisioning
  • [QueueHandler] attribute → Lambda subscription on deploy
  • Per-handler concurrency / batch-size knobs