When to use this module

  • Create a new RabbitMQ queue for async processing.
  • Workflow node requires a delay.
  • Worker completes a task and needs to send a notification.
  • Implement a new background job type.

Architecture Diagram

API Server Worker Service ┌────────────────────┐ ┌───────────────────────────┐ │ RabbitMqPublisher │───Queues───→ │ RabbitMqConsumerWorker │ │ (Infrastructure) │ │ (single BackgroundService) │ └────────────────────┘ │ │ │ │ ├─ WorkflowQueueHandler │ │ ├─ WhatsAppMessageHandler │ │ ├─ WhatsAppTemplateHandler│ │ ├─ MetaWebhookHandler │ │ ├─ ContactImportHandler │ │ └─ SyncMetaTemplateHandler│ ├───────────────────────────┤ │ ScheduledActionWorker │ │ polls every 30 seconds │ ├───────────────────────────┤ │ WorkerSignalRClient │ │ → API NotificationHub │ └───────────────────────────┘

Queue Handlers

HandlerQueue NameWhat It Does
WhatsAppMessageQueueHandlerwhatsapp-messageCalls Meta API to send message
WhatsAppTemplateQueueHandlerwhatsapp-templateTemplate CRUD on Meta API
MetaWebhookQueueHandlermeta-webhookProcess webhook events
ContactImportQueueHandlercontact-importParse CSV + create contacts
SyncMetaTemplateQueueHandlersync-meta-templatePull templates from Meta
WorkflowQueueHandlerworkflowExecute workflow node

IQueueMessageHandler Interface

C#
public interface IQueueMessageHandler
{
    string QueueName { get; }
    Task HandleAsync(string message, IServiceScope scope, CancellationToken ct);
}

Scheduled Actions

Scheduled Action Worker polls every 30 seconds:

Pseudocode
Loop:
  SELECT * FROM ScheduledActions WHERE Status = Pending AND ScheduledFor <= UtcNow
  For each action:
    Mark as Processing
    Dispatch based on type:
      Workflow → resume workflow from delay node
      WorkflowMessageWait → timeout message wait listener
    Mark as Completed (or Failed)
TypeCreated ByDispatches To
WorkflowDelay nodeWorkflowProccessService (resume from next node)
WorkflowMessageWaitButton waitWorkflowProccessService (timeout handler)

How to Extend

How to add a new queue:
  1. Add method to RabbitMqPublisher.csPublishYourTaskAsync()
  2. Create YourQueueHandler.cs implementing IQueueMessageHandler
  3. In Worker/Program.cs: builder.Services.AddSingleton<IQueueMessageHandler, YourQueueHandler>();
  4. RabbitMqConsumerWorker auto-discovers — no other changes needed.
How to add a new scheduled action:
  1. Add value to ScheduledActionTypeEnum
  2. Add case in ScheduledActionWorker.DispatchActionAsync()

Configuration

JSON
{
  "RabbitMq": {
    "HostName": "localhost",
    "Port": 5672,
    "UserName": "guest",
    "Password": "guest",
    "VirtualHost": "/"
  },
  "SignalR": {
    "HubUrl": "https://localhost:5001/notificationhub",
    "RetryDelayMs": 5000
  }
}