Queue ETL: Azure Queue Storage
-
Azure Queue Storage is a Microsoft Azure service that allows for the storage and retrieval of large numbers of messages, enabling communication between applications by allowing them to asynchronously send and receive messages. Each message in a queue can be up to 64 KB in size, and a queue can contain millions of messages, providing a robust and scalable solution for data processing.
-
Create an Azure Queue Storage ETL Task to:
- Extract data from a RavenDB database
- Transform the data using one or more custom scripts
- Load the resulting JSON object to an Azure Queue destination as a CloudEvents message
-
Utilizing this task allows RavenDB to act as an event producer in an Azure Queue architecture.
-
Azure Functions can be triggered to consume and process messages that are sent to Azure queues,
enabling powerful and flexible workflows. The message visibility period and life span in the Queue can be customized through these ETL configuration options. -
Read more about Azure Queue Storage in the platform's official documentation.
-
This article focuses on how to create an Azure Queue Storage ETL task using the Client API.
To define an Azure Queue Storage ETL task from the Studio, see Studio: Azure Queue Storage ETL Task.
For an overview of Queue ETL tasks, see Queue ETL tasks overview. -
In this article:
Add an Azure Queue Storage connection string
-
An Azure Queue Storage ETL task uses an Azure Queue Storage connection string to connect to its destination storage account. The connection string stores the storage account connection details and the authentication settings used to access Azure queues.
-
The ETL task does not store these connection details directly.
Instead, its configuration references the connection string by name through theConnectionStringNameproperty. -
An Azure Queue Storage connection string can be created in any of these ways:
- From the Client API: per-database or server-wide.
- From Studio: per-database, server-wide, or while creating an Azure Queue Storage ETL task.
-
The example below adds a per-database Azure Queue Storage connection string from the Client API.
The connection string is stored in the current database record and can be used by tasks in that database.
Authentication methods
An Azure Queue Storage connection string authenticates in one of three modes.
Set exactly one of these properties in AzureQueueStorageConnectionSettings:
- ConnectionString:
A single Azure Storage connection string.
Forhttp, it must includeDefaultEndpointsProtocol,AccountName,AccountKey, andQueueEndpoint.
Forhttps, it must includeDefaultEndpointsProtocol,AccountName, and the authentication details required by Azure. - EntraId:
Microsoft Entra ID application credentials:StorageAccountName,TenantId,ClientId, andClientSecret. - Passwordless:
Passwordless machine authentication for self-hosted mode, usingStorageAccountName.
The machine account must have the Storage Account Queue Data Contributor role.
Example
- Sync
- Async
// Define an Azure Queue Storage connection string
// ===============================================
var azureQueueStorageConnectionString = new QueueConnectionString
{
// The name used by the Azure Queue Storage ETL task configuration
Name = "azure-queue-storage-connection-string-name",
// Set the queue broker type to Azure Queue Storage
BrokerType = QueueBrokerType.AzureQueueStorage,
// Configure the Azure Queue Storage account connection
AzureQueueStorageConnectionSettings = new AzureQueueStorageConnectionSettings
{
// A storage account connection string
ConnectionString = "DefaultEndpointsProtocol=https;" +
"AccountName=<storage-account-name>;" +
"AccountKey=<storage-account-key>;" +
"EndpointSuffix=core.windows.net"
}
};
// Deploy (send) the connection string to the server
// ==================================================
var putConnectionStringOp =
new PutConnectionStringOperation<QueueConnectionString>(azureQueueStorageConnectionString);
PutConnectionStringResult connectionStringResult =
store.Maintenance.Send(putConnectionStringOp);
// Define an Azure Queue Storage connection string
// ===============================================
var azureQueueStorageConnectionString = new QueueConnectionString
{
// The name used by the Azure Queue Storage ETL task configuration
Name = "azure-queue-storage-connection-string-name",
// Set the queue broker type to Azure Queue Storage
BrokerType = QueueBrokerType.AzureQueueStorage,
// Configure the Azure Queue Storage account connection
AzureQueueStorageConnectionSettings = new AzureQueueStorageConnectionSettings
{
// A storage account connection string
ConnectionString = "DefaultEndpointsProtocol=https;" +
"AccountName=<storage-account-name>;" +
"AccountKey=<storage-account-key>;" +
"EndpointSuffix=core.windows.net"
}
};
// Deploy (send) the connection string to the server
// ==================================================
var putConnectionStringOp =
new PutConnectionStringOperation<QueueConnectionString>(azureQueueStorageConnectionString);
PutConnectionStringResult connectionStringResult =
await store.Maintenance.SendAsync(putConnectionStringOp);
Syntax
- QueueConnectionString
- QueueBrokerType
- AzureQueueStorageConnectionSettings
public sealed class QueueConnectionString : ConnectionString
{
// Set the broker type to QueueBrokerType.AzureQueueStorage
// for an Azure Queue Storage connection string
public QueueBrokerType BrokerType { get; set; }
// Configure this when setting a connection string for Kafka
public KafkaConnectionSettings KafkaConnectionSettings { get; set; }
// Configure this when setting a connection string for RabbitMQ
public RabbitMqConnectionSettings RabbitMqConnectionSettings { get; set; }
// Configure this when setting a connection string for Azure Queue Storage
public AzureQueueStorageConnectionSettings AzureQueueStorageConnectionSettings { get; set; }
// Configure this when setting a connection string for Amazon SQS
public AmazonSqsConnectionSettings AmazonSqsConnectionSettings { get; set; }
// Configure this when setting a connection string for Azure Service Bus
public AzureServiceBusConnectionSettings AzureServiceBusConnectionSettings { get; set; }
}
public enum QueueBrokerType
{
None,
Kafka,
RabbitMq,
AzureQueueStorage,
AmazonSqs,
AzureServiceBus
}
public sealed class AzureQueueStorageConnectionSettings
{
// Set this to authenticate with a storage account connection string
public string ConnectionString { get; set; }
// Set this to authenticate with Microsoft Entra ID application credentials
public EntraId EntraId { get; set; }
// Set this to authenticate with the host machine identity
public Passwordless Passwordless { get; set; }
}
public sealed class EntraId
{
public string StorageAccountName { get; set; }
public string TenantId { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
}
public sealed class Passwordless
{
public string StorageAccountName { get; set; }
}
Add an Azure Queue Storage ETL task
- In this example, the Azure Queue Storage ETL Task will -
- Extract source documents from the "Orders" collection in RavenDB.
- Process each "Order" document using a defined script that creates a new
orderDataobject. - Load the
orderDataobject to the "OrdersQueue" in an Azure Queue Storage.
- For more details about the script and the
loadTomethod, see the transformation script section below.
// Define a transformation script for the task:
// ============================================
Transformation transformation = new Transformation
{
// Define the input collections
Collections = { "Orders" },
ApplyToAllDocuments = false,
// The transformation script
Name = "scriptName",
Script = @"// Create an orderData object
// ==========================
var orderData = {
Id: id(this),
OrderLinesCount: this.Lines.length,
TotalCost: 0
};
// Update the orderData's TotalCost field
// ======================================
for (var i = 0; i < this.Lines.length; i++) {
var line = this.Lines[i];
var cost = (line.Quantity * line.PricePerUnit) * ( 1 - line.Discount);
orderData.TotalCost += cost;
}
// Load the object to the 'OrdersQueue' in Azure
// =============================================
loadToOrdersQueue(orderData, {
Id: id(this),
Type: 'com.example.promotions',
Source: '/promotion-campaigns/summer-sale'
});"
};
// Define the Azure Queue Storage ETL task:
// ========================================
var etlTask = new QueueEtlConfiguration()
{
BrokerType = QueueBrokerType.AzureQueueStorage,
Name = "myAzureQueueEtlTaskName",
ConnectionStringName = "myAzureQueueConStr",
Transforms = { transformation },
// Set to false to allow task failover to another node if current one is down
PinToMentorNode = false
};
// Deploy (send) the task to the server via the AddEtlOperation:
// =============================================================
store.Maintenance.Send(new AddEtlOperation<QueueConnectionString>(etlTask));
-
You have the option to delete documents from your RavenDB database once they have been processed by the Queue ETL task.
-
Set the optional
Queuesproperty in your ETL configuration with the list of Azure queues for which processed documents should be deleted.
var etlTask = new QueueEtlConfiguration()
{
BrokerType = QueueBrokerType.AzureQueueStorage,
Name = "myAzureQueueEtlTaskName",
ConnectionStringName = "myAzureQueueConStr",
Transforms = { transformation },
// Define whether to delete documents from RavenDB after they are sent to the target queue
Queues = new List<EtlQueue>()
{
new()
{
// The name of the Azure queue
Name = "OrdersQueue",
// When set to 'true',
// documents that were processed by the transformation script will be deleted
// from RavenDB after the message is loaded to the "OrdersQueue" in Azure.
DeleteProcessedDocuments = true
}
}
};
store.Maintenance.Send(new AddEtlOperation<QueueConnectionString>(etlTask));
Syntax
public class QueueEtlConfiguration
{
// Set to QueueBrokerType.AzureQueueStorage to define an Azure Queue Storage ETL task
public QueueBrokerType BrokerType { get; set; }
// The ETL task name
public string Name { get; set; }
// The registered connection string name
public string ConnectionStringName { get; set; }
// List of transformation scripts
public List<Transformation> Transforms { get; set; }
// Optional configuration per queue
public List<EtlQueue> Queues { get; set; }
// Set to 'false' to allow task failover to another node if current one is down
public bool PinToMentorNode { get; set; }
}
public class Transformation
{
// The script name
public string Name { get; set; }
// The source RavenDB collections that serve as the input for the script
public List<string> Collections { get; set; }
// Set whether to apply the script on all collections
public bool ApplyToAllDocuments { get; set; }
// The script itself
public string Script { get; set; }
}
public class EtlQueue
{
// The Azure queue name
public string Name { get; set; }
// Delete processed documents when set to 'true'
public bool DeleteProcessedDocuments { get; set; }
}
The transformation script
The basic characteristics of an Azure Queue Storage ETL script are similar to those of other ETL types.
The script defines what data to extract from the source document, how to transform this data,
and which Azure Queue to load it to.
The loadTo method
To specify which Azure queue to load the data into, use either of the following methods in your script.
The two methods are equivalent, offering alternative syntax:
-
loadTo<QueueName>(obj, {attributes})- Here the target is specified as part of the function name.
- The target <QueueName> in this syntax is Not a variable and cannot be used as one,
it is simply a string literal of the target's name.
-
loadTo('QueueName', obj, {attributes})- Here the target is passed as an argument to the method.
- Separating the target name from the
loadTocommand makes it possible to include symbols like'-'and'.'in target names. This is not possible when theloadTo<QueueName>syntax is used because including special characters in the name of a JavaScript function makes it invalid.
Parameter Type Description QueueName string The name of the Azure Queue obj object The object to transfer attributes object An object with optional & required CloudEvents attributes
For example, the following two calls, which load data to "OrdersQueue", are equivalent:
loadToOrdersQueue(obj, {attributes})loadTo('OrdersQueue', obj, {attributes})The following is a sample script that processes documents from the Orders collection:
// Create an orderData object
// ==========================
var orderData = {
Id: id(this),
OrderLinesCount: this.Lines.length,
TotalCost: 0
};
// Update the orderData's TotalCost field
// ======================================
for (var i = 0; i < this.Lines.length; i++) {
var line = this.Lines[i];
var cost = (line.Quantity * line.PricePerUnit) * ( 1 - line.Discount);
orderData.TotalCost += cost;
}
// Load the object to the "OrdersQueue" in Azure
// =============================================
loadToOrdersQueue(orderData, {
Id: id(this),
Type: 'com.example.promotions',
Source: '/promotion-campaigns/summer-sale'
})
Note:
The queue name defined in the transform script must follow the set of rules outlined in:
Naming Queues and Metadata.