Skip to main content

Enqueueing from outside the processing host

A website or API can produce messages while a separate Nexus application processes them. Share the message contract and stable queue names between the applications. There are three ways to publish.

Enqueueing using the Queueing package​

Queueing is included in CommerceMind.Nexus; there is no separate v3 CommerceMind.Nexus.Queueing package. Shared message contracts can reference CommerceMind.Nexus.Abstractions:

[Queue("order_exports")]
public class OrderExportMessage : IQueueMessage
{
public string OrderId { get; set; } = "";
}

The processing host registers queues and their processing implementation:

builder.Services.AddNexus()
.AddDatabasePollingInstanceEvents()
.AddQueues(options =>
{
options.AssembliesToScanForQueueMessages.Add(typeof(OrderExportMessage).Assembly);
})
.AddJobs(options =>
{
options.AssembliesToScanForJobs.Add(typeof(OrderExportJob).Assembly);
})
.AddPostgresConnection()
.Build();

OrderExportJob implements IQueueJob<OrderExportMessage> or IBatchQueueJob<OrderExportMessage>. Alternatively, register AddQueueProcessors() for a distributed processor instead of the queue job.

The producing host registers the same queues and database, without registering processing:

builder.Services.AddNexus()
.AddDatabasePollingInstanceEvents(options =>
{
options.BrokerType = InstanceEventBrokerType.ProduceEvents;
})
.AddQueues(options =>
{
options.AssembliesToScanForQueueMessages.Add(typeof(OrderExportMessage).Assembly);
})
.AddPostgresConnection()
.Build();

Inject the scoped IEnqueuer<OrderExportMessage> into the producer's controller/application operation and call EnqueueAsync(). AddQueues() alone does not register jobs or distributed processors, though it does initialize queue schemas and run queue maintenance. Producers need migration permissions when initialization changes schema.

Both hosts use the same database and activation store. Configure a shared instance-event broker to wake workers promptly; a producer-only broker avoids listening for those events in the producer. If using Redis activation storage instead of the database default, configure it consistently on both hosts.

The queue job's saved schedule determines whether it starts on readiness or waits for its cron schedule. The producer does not need a separate enqueue-and-start call. With EF integration, publishing to a database queue joins the producer's scoped unit of work.

This approach requires the producer to access the Nexus database. Use the HTTP client when that access is undesirable. In-memory queues must be published through the API of their single owning instance, not by writing their fallback database from another application.

Enqueueing using the ApiClient package​

CommerceMind.Nexus.ApiClient publishes through the Nexus HTTP API without local database access, queue storage, processing, or an instance-event broker. Configure the HTTP client and contract assemblies:

builder.Services.AddHttpClient(ApiEnqueuerOptions.DefaultHttpClientName)
.ConfigureHttpClient(client =>
{
client.BaseAddress = new Uri("https://nexus-host.example.com/nexus/");
// Configure authentication headers/handlers here if needed.
});

builder.Services.AddNexus().AddApiEnqueuers(options =>
{
options.AssembliesToScanForQueueMessages.Add(typeof(OrderExportMessage).Assembly);
}).Build();

The base address must match the host's API base path. Ordinary queues can be reached through IEnqueuer<T>; use IApiEnqueuer<T> when explicitly selecting a remote named destination:

await apiEnqueuer.EnqueueAsync("order_exports", message);

Named destinations do not need per-name client registrations. The server validates the destination and runs any virtual transformers on that host. A remote enqueue is immediate and cannot roll back with a producer's EF transaction; use a local database outbox when delivery must follow that transaction.

Change ApiEnqueuerOptions.HttpClientName to use a different named HTTP client. To distinguish implementations, use IApiEnqueuer, IVirtualEnqueuer, or IDatabaseEnqueuer and their typed equivalents where available. These are still scoped services; singleton callers should create an operation scope.

Enqueueing over HTTP using the API​

Non-.NET clients can call POST /api/queues/{queueName} or POST /api/queues/{queueName}/batch, relative to the configured API base path. The create-item body wraps the payload in message:

{
"message": { "OrderId": "123" },
"priority": 10
}

Queue creation payloads no longer have startProcessing; readiness follows the server's processing mode. See the API reference for batch and context fields. Queue webhooks accept raw message JSON instead of the create-item wrapper.

For named/generated destinations, always select the queue explicitly. To run generated ShouldEnqueue routing, send to its configured virtual RoutingQueueName rather than a concrete destination. See named queues and generated queues.