Azure Queue Storage
Azure Queue Storage provides asynchronous messaging for image lifecycle operations — deletion cleanup, caching, and orchestration redeployment. The Infrastructure package implements a polymorphic QueueService that is registered multiple times using marker interfaces — one per queue — allowing strongly typed DI injection for specific queues without shared state.
Registration
Queue storage is registered as part of the AddAlertCAStorageServices extension method:
services.AddAlertCAStorageServices(configuration);
Each queue interface is bound to a QueueService instance with the correct queue name from configuration:
services.AddScoped<ISingleImageMetadataDeleteQueue>(provider =>
{
var queueServiceClient = provider.GetRequiredService<QueueServiceClient>();
return new QueueService(queueServiceClient, storageQueueOptions.DeleteSingleImageQueue);
});
services.AddScoped<ICacheSingleImageQueue>(provider =>
{
var queueServiceClient = provider.GetRequiredService<QueueServiceClient>();
return new QueueService(queueServiceClient, storageQueueOptions.CacheSingleImageQueue);
});
// ... repeated for all 9 queue interfaces
Configuration
{
"StorageQueueOptions": {
"DeleteSingleImageQueue": "",
"DeletePanoImageQueue": "",
"DeletePreStitchImageQueue": "",
"DeleteVideoQueue": "",
"CacheSingleImageQueue": "",
"CachePreStitchZipArchiveQueue": "",
"CachePanoImageQueue": "",
"OrchestrationRedeployQueue": "",
"ProcessAiDetectionsQueue": ""
}
}
The QueueServiceClient URL is constructed from the blob storage account name: https://{AccountName}.queue.core.windows.net. Authentication uses DefaultAzureCredential.
Architecture
QueueService API
The QueueService class implements IQueueService and all 9 typed marker interfaces via a single implementation:
public class QueueService(QueueServiceClient queueServiceClient, string queueName) :
IQueueService, IPreStitchImageDeleteQueue, IPanoImageMetadataDeleteQueue,
ISingleImageMetadataDeleteQueue, ICacheSingleImageQueue,
ICachePrestitchZipArchiveQueue, ICachePanoImageQueue, IVideoMetadataDeleteQueue,
IOrchestrationRedeployQueue, IProcessAiDetections
| Method | Description |
|---|---|
SendMessageAsync(string message) | UTF-8 encodes, then Base64-encodes and enqueues a message |
DeleteMessageAsync(string messageId, string popReceipt) | Removes a processed message from the queue |
Messages are serialized to JSON by the caller and Base64-encoded by QueueService before sending.
Queue Purposes
| Queue | Interface | Category | Purpose |
|---|---|---|---|
| DeleteSingleImageQueue | ISingleImageMetadataDeleteQueue | Delete | Triggers cleanup of single image blobs and metadata |
| DeletePanoImageQueue | IPanoImageMetadataDeleteQueue | Delete | Triggers cleanup of panoramic image blobs and metadata |
| DeletePreStitchImageQueue | IPreStitchImageDeleteQueue | Delete | Triggers cleanup of pre-stitch image blobs and metadata |
| DeleteVideoQueue | IVideoMetadataDeleteQueue | Delete | Triggers cleanup of video blobs and metadata |
| CacheSingleImageQueue | ICacheSingleImageQueue | Cache | Triggers caching of single camera images |
| CachePreStitchZipArchiveQueue | ICachePrestitchZipArchiveQueue | Cache | Triggers caching of pre-stitch ZIP archives |
| CachePanoImageQueue | ICachePanoImageQueue | Cache | Triggers caching of panoramic images |
| OrchestrationRedeployQueue | IOrchestrationRedeployQueue | Orchestration | Triggers redeployment of acquisition orchestration functions |
| ProcessAiDetectionsQueue | IProcessAiDetections | AI Detection | Triggers processing of Condor AI detection events |
Usage Example
using Alert.CA.Infrastructure.Services.Interfaces;
public class ImageCleanupService(
ISingleImageMetadataDeleteQueue deleteQueue,
ICacheSingleImageQueue cacheQueue)
{
public async Task QueueImageForDeletion(string blobName)
{
await deleteQueue.SendMessageAsync(blobName);
}
public async Task QueueImageForCaching(string message)
{
await cacheQueue.SendMessageAsync(message);
}
}
Each queue consumer receives the Base64-decoded message and processes it accordingly. The Infrastructure package only provides the sending side — consuming is handled by the respective Azure Function triggers or background services in each project.