|
Add this skill
npx mdskills install sickn33/azure-storage-queue-tsComprehensive Azure Queue Storage SDK reference with excellent examples and patterns
1---2name: azure-storage-queue-ts3description: |4 Azure Queue Storage JavaScript/TypeScript SDK (@azure/storage-queue) for message queue operations. Use for sending, receiving, peeking, and deleting messages in queues. Supports visibility timeout, message encoding, and batch operations. Triggers: "queue storage", "@azure/storage-queue", "QueueServiceClient", "QueueClient", "send message", "receive message", "dequeue", "visibility timeout".5package: "@azure/storage-queue"6---78# @azure/storage-queue (TypeScript/JavaScript)910SDK for Azure Queue Storage operations — send, receive, peek, and manage messages in queues.1112## Installation1314```bash15npm install @azure/storage-queue @azure/identity16```1718**Current Version**: 12.x19**Node.js**: >= 18.0.02021## Environment Variables2223```bash24AZURE_STORAGE_ACCOUNT_NAME=<account-name>25AZURE_STORAGE_ACCOUNT_KEY=<account-key>26# OR connection string27AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...28```2930## Authentication3132### DefaultAzureCredential (Recommended)3334```typescript35import { QueueServiceClient } from "@azure/storage-queue";36import { DefaultAzureCredential } from "@azure/identity";3738const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;39const client = new QueueServiceClient(40 `https://${accountName}.queue.core.windows.net`,41 new DefaultAzureCredential()42);43```4445### Connection String4647```typescript48import { QueueServiceClient } from "@azure/storage-queue";4950const client = QueueServiceClient.fromConnectionString(51 process.env.AZURE_STORAGE_CONNECTION_STRING!52);53```5455### StorageSharedKeyCredential (Node.js only)5657```typescript58import { QueueServiceClient, StorageSharedKeyCredential } from "@azure/storage-queue";5960const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;61const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!;6263const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);64const client = new QueueServiceClient(65 `https://${accountName}.queue.core.windows.net`,66 sharedKeyCredential67);68```6970### SAS Token7172```typescript73import { QueueServiceClient } from "@azure/storage-queue";7475const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;76const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!;7778const client = new QueueServiceClient(79 `https://${accountName}.queue.core.windows.net${sasToken}`80);81```8283## Client Hierarchy8485```86QueueServiceClient (account level)87└── QueueClient (queue level)88 └── Messages (send, receive, peek, delete)89```9091## Queue Operations9293### Create Queue9495```typescript96const queueClient = client.getQueueClient("my-queue");97await queueClient.create();9899// Or create if not exists100await queueClient.createIfNotExists();101```102103### List Queues104105```typescript106for await (const queue of client.listQueues()) {107 console.log(queue.name);108}109110// With prefix filter111for await (const queue of client.listQueues({ prefix: "task-" })) {112 console.log(queue.name);113}114```115116### Delete Queue117118```typescript119await queueClient.delete();120121// Or delete if exists122await queueClient.deleteIfExists();123```124125### Get Queue Properties126127```typescript128const properties = await queueClient.getProperties();129console.log("Approximate message count:", properties.approximateMessagesCount);130console.log("Metadata:", properties.metadata);131```132133### Set Queue Metadata134135```typescript136await queueClient.setMetadata({137 department: "engineering",138 priority: "high",139});140```141142## Message Operations143144### Send Message145146```typescript147const queueClient = client.getQueueClient("my-queue");148149// Simple message150await queueClient.sendMessage("Hello, World!");151152// With options153await queueClient.sendMessage("Delayed message", {154 visibilityTimeout: 60, // Hidden for 60 seconds155 messageTimeToLive: 3600, // Expires in 1 hour156});157158// JSON message (must be string)159const task = { type: "process", data: { id: 123 } };160await queueClient.sendMessage(JSON.stringify(task));161```162163### Receive Messages164165```typescript166// Receive up to 32 messages (default: 1)167const response = await queueClient.receiveMessages({168 numberOfMessages: 10,169 visibilityTimeout: 30, // 30 seconds to process170});171172for (const message of response.receivedMessageItems) {173 console.log("Message ID:", message.messageId);174 console.log("Content:", message.messageText);175 console.log("Dequeue Count:", message.dequeueCount);176 console.log("Pop Receipt:", message.popReceipt);177178 // Process the message...179180 // Delete after processing181 await queueClient.deleteMessage(message.messageId, message.popReceipt);182}183```184185### Peek Messages186187Peek without removing from queue (no visibility timeout).188189```typescript190const response = await queueClient.peekMessages({191 numberOfMessages: 5,192});193194for (const message of response.peekedMessageItems) {195 console.log("Message ID:", message.messageId);196 console.log("Content:", message.messageText);197 // Note: No popReceipt - cannot delete peeked messages198}199```200201### Update Message202203Extend visibility timeout or update content.204205```typescript206// Receive a message207const response = await queueClient.receiveMessages();208const message = response.receivedMessageItems[0];209210if (message) {211 // Update content and extend visibility212 const updateResponse = await queueClient.updateMessage(213 message.messageId,214 message.popReceipt,215 "Updated content",216 60 // New visibility timeout in seconds217 );218219 // Use new popReceipt for subsequent operations220 console.log("New pop receipt:", updateResponse.popReceipt);221}222```223224### Delete Message225226```typescript227// After receiving228const response = await queueClient.receiveMessages();229const message = response.receivedMessageItems[0];230231if (message) {232 await queueClient.deleteMessage(message.messageId, message.popReceipt);233}234```235236### Clear All Messages237238```typescript239await queueClient.clearMessages();240```241242## Message Processing Patterns243244### Basic Worker Pattern245246```typescript247async function processQueue(queueClient: QueueClient): Promise<void> {248 while (true) {249 const response = await queueClient.receiveMessages({250 numberOfMessages: 10,251 visibilityTimeout: 30,252 });253254 if (response.receivedMessageItems.length === 0) {255 // No messages, wait before polling again256 await sleep(5000);257 continue;258 }259260 for (const message of response.receivedMessageItems) {261 try {262 await processMessage(message.messageText);263 await queueClient.deleteMessage(message.messageId, message.popReceipt);264 } catch (error) {265 console.error(`Failed to process message ${message.messageId}:`, error);266 // Message will become visible again after timeout267 }268 }269 }270}271272async function processMessage(content: string): Promise<void> {273 const task = JSON.parse(content);274 // Process task...275}276277function sleep(ms: number): Promise<void> {278 return new Promise((resolve) => setTimeout(resolve, ms));279}280```281282### Poison Message Handling283284```typescript285const MAX_DEQUEUE_COUNT = 5;286287async function processWithPoisonHandling(288 queueClient: QueueClient,289 poisonQueueClient: QueueClient290): Promise<void> {291 const response = await queueClient.receiveMessages({292 numberOfMessages: 10,293 visibilityTimeout: 30,294 });295296 for (const message of response.receivedMessageItems) {297 if (message.dequeueCount > MAX_DEQUEUE_COUNT) {298 // Move to poison queue299 await poisonQueueClient.sendMessage(message.messageText);300 await queueClient.deleteMessage(message.messageId, message.popReceipt);301 console.log(`Moved message ${message.messageId} to poison queue`);302 continue;303 }304305 try {306 await processMessage(message.messageText);307 await queueClient.deleteMessage(message.messageId, message.popReceipt);308 } catch (error) {309 console.error(`Processing failed (attempt ${message.dequeueCount}):`, error);310 }311 }312}313```314315### Batch Processing with Visibility Extension316317```typescript318async function processBatchWithExtension(queueClient: QueueClient): Promise<void> {319 const response = await queueClient.receiveMessages({320 numberOfMessages: 1,321 visibilityTimeout: 60,322 });323324 const message = response.receivedMessageItems[0];325 if (!message) return;326327 let popReceipt = message.popReceipt;328329 // Start visibility extension timer330 const extensionInterval = setInterval(async () => {331 try {332 const updateResponse = await queueClient.updateMessage(333 message.messageId,334 popReceipt,335 message.messageText,336 60 // Extend by another 60 seconds337 );338 popReceipt = updateResponse.popReceipt;339 } catch (error) {340 console.error("Failed to extend visibility:", error);341 }342 }, 45000); // Extend every 45 seconds343344 try {345 await longRunningProcess(message.messageText);346 await queueClient.deleteMessage(message.messageId, popReceipt);347 } finally {348 clearInterval(extensionInterval);349 }350}351```352353## Message Encoding354355By default, messages are Base64 encoded. You can customize this:356357```typescript358import { QueueClient } from "@azure/storage-queue";359360// Custom encoder/decoder for plain text361const queueClient = new QueueClient(362 `https://${accountName}.queue.core.windows.net/my-queue`,363 credential,364 {365 messageEncoding: "text", // "base64" (default) or "text"366 }367);368369// Or with custom encoder370const customQueueClient = new QueueClient(371 `https://${accountName}.queue.core.windows.net/my-queue`,372 credential,373 {374 messageEncoding: {375 encode: (message: string) => Buffer.from(message).toString("base64"),376 decode: (message: string) => Buffer.from(message, "base64").toString(),377 },378 }379);380```381382## SAS Token Generation (Node.js only)383384### Generate Queue SAS385386```typescript387import {388 QueueSASPermissions,389 generateQueueSASQueryParameters,390 StorageSharedKeyCredential,391} from "@azure/storage-queue";392393const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);394395const sasToken = generateQueueSASQueryParameters(396 {397 queueName: "my-queue",398 permissions: QueueSASPermissions.parse("raup"), // read, add, update, process399 startsOn: new Date(),400 expiresOn: new Date(Date.now() + 3600 * 1000), // 1 hour401 },402 sharedKeyCredential403).toString();404405const sasUrl = `https://${accountName}.queue.core.windows.net/my-queue?${sasToken}`;406```407408### Generate Account SAS409410```typescript411import {412 AccountSASPermissions,413 AccountSASResourceTypes,414 AccountSASServices,415 generateAccountSASQueryParameters,416} from "@azure/storage-queue";417418const sasToken = generateAccountSASQueryParameters(419 {420 services: AccountSASServices.parse("q").toString(), // queue421 resourceTypes: AccountSASResourceTypes.parse("sco").toString(),422 permissions: AccountSASPermissions.parse("rwdlacupi"),423 expiresOn: new Date(Date.now() + 24 * 3600 * 1000),424 },425 sharedKeyCredential426).toString();427```428429## Error Handling430431```typescript432import { RestError } from "@azure/storage-queue";433434try {435 await queueClient.sendMessage("test");436} catch (error) {437 if (error instanceof RestError) {438 switch (error.statusCode) {439 case 404:440 console.log("Queue not found");441 break;442 case 400:443 console.log("Bad request - message too large or invalid");444 break;445 case 403:446 console.log("Access denied");447 break;448 case 409:449 console.log("Queue already exists or being deleted");450 break;451 default:452 console.error(`Storage error ${error.statusCode}: ${error.message}`);453 }454 }455 throw error;456}457```458459## TypeScript Types Reference460461```typescript462import {463 // Clients464 QueueServiceClient,465 QueueClient,466467 // Authentication468 StorageSharedKeyCredential,469 AnonymousCredential,470471 // SAS472 QueueSASPermissions,473 AccountSASPermissions,474 AccountSASServices,475 AccountSASResourceTypes,476 generateQueueSASQueryParameters,477 generateAccountSASQueryParameters,478479 // Messages480 DequeuedMessageItem,481 PeekedMessageItem,482 QueueSendMessageResponse,483 QueueReceiveMessageResponse,484 QueueUpdateMessageResponse,485486 // Queue487 QueueItem,488 QueueGetPropertiesResponse,489490 // Errors491 RestError,492} from "@azure/storage-queue";493```494495## Message Limits496497| Limit | Value |498|-------|-------|499| Max message size | 64 KB |500| Max visibility timeout | 7 days |501| Max time-to-live | 7 days (or -1 for infinite) |502| Max messages per receive | 32 |503| Default visibility timeout | 30 seconds |504505## Best Practices5065071. **Use DefaultAzureCredential** — Prefer AAD over connection strings/keys5082. **Always delete after processing** — Prevent duplicate processing5093. **Handle poison messages** — Move failed messages to a dead-letter queue5104. **Use appropriate visibility timeout** — Set based on expected processing time5115. **Extend visibility for long tasks** — Update message to prevent timeout5126. **Use JSON for structured data** — Serialize objects to JSON strings5137. **Check dequeueCount** — Detect repeatedly failing messages5148. **Use batch receive** — Receive multiple messages for efficiency515516## Platform Differences517518| Feature | Node.js | Browser |519|---------|---------|---------|520| `StorageSharedKeyCredential` | ✅ | ❌ |521| SAS generation | ✅ | ❌ |522| DefaultAzureCredential | ✅ | ❌ |523| Anonymous/SAS access | ✅ | ✅ |524| All message operations | ✅ | ✅ |525
Full transparency — inspect the skill content before installing.