Azure Service Bus

The Azure Service Bus SDKs, unchanged, with a connection string: queues, topics, subscriptions with filters, sessions, scheduling and dead-lettering over AMQP 1.0.

Connection string

Endpoint=sb://amqp.powerqueue.link/;SharedAccessKeyName=<your-identifier>;SharedAccessKey=anything

Python (azure-servicebus)

pip install azure-servicebus. A queue, with no setup:

from azure.servicebus import ServiceBusClient, ServiceBusMessage

CONNECTION_STRING = (
    "Endpoint=sb://amqp.powerqueue.link/;"
    "SharedAccessKeyName=<your-identifier>;SharedAccessKey=anything"
)

with ServiceBusClient.from_connection_string(CONNECTION_STRING) as client:
    with client.get_queue_sender("invoices") as sender:
        sender.send_messages([ServiceBusMessage(f"invoice {i}") for i in range(3)])
    with client.get_queue_receiver("invoices", max_wait_time=5) as receiver:
        for message in receiver:
            print(str(message))
            receiver.complete_message(message)

A topic with a filtered subscription, created through the administration API:

from azure.servicebus import ServiceBusClient, ServiceBusMessage
from azure.servicebus.management import ServiceBusAdministrationClient, SqlRuleFilter

admin = ServiceBusAdministrationClient.from_connection_string(CONNECTION_STRING)
admin.create_topic("alerts")
admin.create_subscription("alerts", "errors")
admin.delete_rule("alerts", "errors", "$Default")
admin.create_rule("alerts", "errors", "only-errors", filter=SqlRuleFilter("level = 'error'"))

with ServiceBusClient.from_connection_string(CONNECTION_STRING) as client:
    with client.get_topic_sender("alerts") as sender:
        sender.send_messages(ServiceBusMessage("disk full", application_properties={"level": "error"}))
        sender.send_messages(ServiceBusMessage("all good", application_properties={"level": "info"}))
    with client.get_subscription_receiver("alerts", "errors", max_wait_time=5) as receiver:
        for message in receiver:
            print(str(message))
            receiver.complete_message(message)

JavaScript (@azure/service-bus)

npm install @azure/service-bus, then run as an ES module:

import { ServiceBusClient } from "@azure/service-bus";

const connectionString =
  "Endpoint=sb://amqp.powerqueue.link/;SharedAccessKeyName=<your-identifier>;SharedAccessKey=anything";
const client = new ServiceBusClient(connectionString);

const sender = client.createSender("invoices");
await sender.sendMessages({ body: "hello", messageId: "invoice-1" });
await sender.close();

const receiver = client.createReceiver("invoices");
const messages = await receiver.receiveMessages(10, { maxWaitTimeInMs: 5000 });
for (const message of messages) {
  console.log(message.body);
  await receiver.completeMessage(message);
}
await receiver.close();
await client.close();

C# (.NET, Azure.Messaging.ServiceBus)

dotnet add package Azure.Messaging.ServiceBus:

using Azure.Messaging.ServiceBus;

var connectionString =
    "Endpoint=sb://amqp.powerqueue.link/;SharedAccessKeyName=<your-identifier>;SharedAccessKey=anything";
await using var client = new ServiceBusClient(connectionString);

await using ServiceBusSender sender = client.CreateSender("invoices");
await sender.SendMessageAsync(new ServiceBusMessage("hello"));

await using ServiceBusReceiver receiver = client.CreateReceiver("invoices");
var messages = await receiver.ReceiveMessagesAsync(maxMessages: 10, maxWaitTime: TimeSpan.FromSeconds(5));
foreach (var message in messages)
{
    Console.WriteLine(message.Body.ToString());
    await receiver.CompleteMessageAsync(message);
}

Supported

Differences from Azure Service Bus

Messages from other interfaces

Bodies sent through the other interfaces arrive as a single data section of their bytes. A message you send whose body is an AMQP value (a number, map, list and so on) or sequence reads back the same through Service Bus, and as JSON text, marked x-pq-body-encoding = json where the reader can carry a mark, through the others; a string or binary value crosses as its plain bytes. AMQP 0-9-1 headers and SQS and Pub/Sub attributes arrive as application properties with their types; an AMQP table or array header as JSON text, a decimal as its decimal text. Property names starting x-pq- are the service's and are not passed on.

The full rules, with examples: Using one queue from several interfaces.

Errors

SituationAMQP condition or HTTP statusPython exception
Key name is not a tenant identifier (for example RootManageSharedAccessKey)401 on the CBS token, with the identifier help text; administration API 401ServiceBusAuthenticationError; ClientAuthenticationError
Too many new tenants from your address, or the service is fullcom.microsoft:server-busy; administration API 503ServiceBusServerBusyError
More than 100 requests a second (after a burst of 200): each message sent, link attached and management request countscom.microsoft:server-busy; administration API 503ServiceBusServerBusyError (retried with back-off)
More than 50 connections from your addressconnection closedServiceBusError
Message over 256 KiBamqp:link:message-size-exceededMessageSizeExceededError
A 101st queue, topic or subscriptionadministration API 403; by sending or receiving, amqp:resource-limit-exceededHttpResponseError; ServiceBusQuotaExceededError
Queue holding 1,000 messages, or a tenant holding 16 MiB of messagesamqp:resource-limit-exceededServiceBusQuotaExceededError
Entity descriptions and rules of a tenant, with its other settings, growing past 1 MiB together403 (QuotaExceeded) or amqp:resource-limit-exceededHttpResponseError or ServiceBusQuotaExceededError
Time to live or scheduled enqueue time beyond 1 hourcom.microsoft:argument-out-of-range; administration API 400ServiceBusError; HttpResponseError
More than 16 sessions or 128 links on one connectionamqp:resource-limit-exceededServiceBusError