Enqueueing from outside the job service
The typical scenario is to deploy the code that runs background jobs as a separate service from the rest of your application(s). Eg a public website that takes traffic from public users is deployed separately from the service running background job. But you still want to enqueue messages from the public website that the background jobs will process. To split this up you have three options.
Enqueueing using the Queueing package
The NuGet package CommerceMind.Nexus.Queueing
can be included in other .NET projects than the one running background jobs. This means that the .NET project for your public website or other non-jobs service can still enqueue messages. In order for this to work you need to keep your IQueueMessage
implementation classes in a separate .NET project that is used by both your background job service and your website. A simplified example:
Core project:
namespace MyNamespace.Core
{
public class MyQueueMessage : IQueueMessage { }
}
Jobs project:
namespace MyNamespace.Jobs
{
public class MyMessageJob : IScheduledQueueJob<MyQueueMessage>
{
// Implementation excluded for brevity
}
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder
.AddNexus()
.AddDatabasePollingInstanceEvents()
// Or: .AddAzureServiceBusInstanceEvents()
.AddScheduledJobs()
.AddQueues(options =>
{
options.AssembliesToScanForQueueMessages.Add(typeof(MyQueueMessage).Assembly);
})
.AddPostgresConnection()
.Build();
var app = builder.Build();
app.Run();
}
}
Website project:
namespace MyNamespace.Website
{
public class MyMessageController : Controller
{
private IEnqueuer<MyQueueMessage> _enqueuer;
public MyMessageController(IEnqueuer<MyQueueMessage> enqueuer)
{
_enqueuer = enqueuer;
}
// Implementation excluded for brevity
}
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddNexus()
.AddDatabasePollingInstanceEvents(options =>
{
options.BrokerType = InstanceEventBrokerType.ProduceEvents;
})
// Or: .AddAzureServiceBusInstanceEvents(options => ...)
.AddQueues(options =>
{
options.AssembliesToScanForQueueMessages.Add(typeof(MyQueueMessage).Assembly);
})
.AddPostgresConnection()
.Build();
var app = builder.Build();
app.Run();
}
}
Note that the website project still needs to configure instance events when only running the queue system, but we can signal that we're only producing instance events and are not interested in listening to them. This skips setting up any polling for messages on the website application.
Now both the jobs and website project uses the queue system and has a reference to the core project to use the MyQueueMessage
class. The website project can use IEnqueuer<MyQueueMessage>
to enqueue messages that the jobs project will pick up and process.
This is the simplest approach but has the downside that your website project needs access to the database containing the queues which may or may not be a problem for you. If it is a problem you probably want to enqueue through the API instead.
Enqueueing using the ApiClient package
There's a separate NuGet package called CommerceMind.Nexus.Queueing.ApiClient
that contains an IEnqueuer<TMessage>
implementation that enqueues messages over the API.
You install the package and configure it like this in Program.cs
:
builder.Services.AddHttpClient(ApiEnqueuerOptions.DefaultHttpClientName).ConfigureHttpClient(client =>
{
client.BaseAddress = new Uri("https://the-url-to-the-api.com/");
});
builder.Services.AddNexus().AddApiEnqueuers(options =>
{
// Important to register assemblies which contains IQueueMessage classes
options.AssembliesToScanForQueueMessages.Add(typeof(MyMessage).Assembly);
});
This will find all IQueueMessage
classes and register IEnqueuer<TMessage>
s for them that can be used to enqueue messages through the API. This means that you don't have to reference any of the other NuGet packages, and your deployed application won't need access to the database.
Registering an HTTP client is important since it lets you set the url to the API as well as setting additional headers such as authentication. If you don't want the default HTTP client name you can change it by doing:
builder.Services.AddHttpClient("my-http-client").ConfigureHttpClient(...);
builder.Services.AddNexus().AddApiEnqueuers(options =>
{
options.HttpClientName = "my-http-client";
});
If you need to differentiate between an API enqueuer, a database, or virtual enqueuer there's these additional interfaces that you can use to check against: IApiEnqueuer
, IVirtualEnqueuer
, and IDatabaseEnqueuer
.
Enqueueing over HTTP using the API
If you want to enueue over the API yourself without using the CommerceMind.Nexus.Queueing.ApiClient
that's of course also possible, but should only be done if you really can't use the API client package. Such as if you want to enqueue from a non-.NET solution.
The included API has endpoints to enqueue messages over HTTP, more specifically the endpoints POST /api/queues/{queueName}
and POST /api/queues/{queueName}/batch
that you can find in the Swagger docs.