Configurando Azure Functions para Acesso Eficiente a Filas do Azure com SOLID e Padrão Factory em TypeScript

Cláudio Rapôso
4 min readJul 17, 2024

Este é o terceiro artigo de uma série sobre como configurar Azure Functions para acesso a serviços do Azure utilizando os princípios SOLID (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion). Nos artigos anteriores, abordamos o acesso ao Azure Blob Storage e às tabelas do Azure. Neste artigo, focaremos no acesso a filas do Azure utilizando o Azure Storage Queue. Caso sinta vontade de entender como integrar o Azure Table Storage veja o artigo abaixo:

Passo 1: Configuração do Ambiente

Antes de começar, certifique-se de ter as seguintes dependências instaladas:

npm install @azure/identity @azure/storage-queue

OBS: Caso precise ver os Passos 1 ao 3 veja o artigo anterior sobre o tema:

Passo 4: Criando a Fábrica QueueServiceClientFactory

Implementaremos uma fábrica para criar instâncias de QueueServiceClient com base no provedor de credenciais selecionado.

import { QueueServiceClient } from "@azure/storage-queue";

/**
* Factory for creating instances of QueueServiceClient.
*/
class QueueServiceClientFactory {
private accountUrl: string;
private credentialProvider: CredentialProvider;

/**
* Creates an instance of QueueServiceClientFactory.
* @param {string} accountUrl - The account URL for the QueueServiceClient.
* @param {CredentialProvider} credentialProvider - The provider for Azure credentials.
*/
constructor(accountUrl: string, credentialProvider: CredentialProvider) {
this.accountUrl = accountUrl;
this.credentialProvider = credentialProvider;
}

/**
* Creates a QueueServiceClient instance.
* @returns {QueueServiceClient} The QueueServiceClient instance.
*/
createQueueServiceClient(): QueueServiceClient {
const credential = this.credentialProvider.getCredential();
return new QueueServiceClient(this.accountUrl, credential);
}
}

Passo 5: Utilizando a Fábrica em uma Azure Function

Vamos aplicar nossa fábrica dentro de Azure Functions para acesso seguro e eficiente às filas do Azure.

Exemplo 1: Azure Function com Managed Identity Atribuída ao Sistema

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { QueueServiceClientFactory } from "./QueueServiceClientFactory";
import { SystemAssignedManagedIdentityCredentialProvider } from "./SystemAssignedManagedIdentityCredentialProvider";

/**
* Azure Function triggered by an HTTP request.
* @param {Context} context - The Azure Function context object.
* @param {HttpRequest} req - The HTTP request object.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const accountUrl = process.env.AZURE_STORAGEQUEUE_RESOURCEENDPOINT;
const credentialProvider = new SystemAssignedManagedIdentityCredentialProvider();
const queueServiceClientFactory = new QueueServiceClientFactory(accountUrl, credentialProvider);

const queueServiceClient = queueServiceClientFactory.createQueueServiceClient();
const queueClient = queueServiceClient.getQueueClient(queueName);
await queueClient.sendMessage("Hello World!");

context.res = {
status: 200,
body: { text: "menssage sent" }
};
};

export default httpTrigger;

Exemplo 2: Azure Function com Managed Identity Atribuída ao Usuário

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { QueueServiceClientFactory } from "./QueueServiceClientFactory";
import { UserAssignedManagedIdentityCredentialProvider } from "./UserAssignedManagedIdentityCredentialProvider";

/**
* Azure Function triggered by an HTTP request.
* @param {Context} context - The Azure Function context object.
* @param {HttpRequest} req - The HTTP request object.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const accountUrl = process.env.AZURE_STORAGEQUEUE_RESOURCEENDPOINT;
const clientId = process.env.AZURE_STORAGEQUEUE_CLIENTID;
const credentialProvider = new UserAssignedManagedIdentityCredentialProvider(clientId);
const queueServiceClientFactory = new QueueServiceClientFactory(accountUrl, credentialProvider);

const queueServiceClient = queueServiceClientFactory.createQueueServiceClient();
const queueClient = queueServiceClient.getQueueClient(queueName);
await queueClient.sendMessage("Hello World!");

context.res = {
status: 200,
body: { text: "menssage sent" }
};
};

export default httpTrigger;

Exemplo 3: Azure Function com Service Principal

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { QueueServiceClientFactory } from "./QueueServiceClientFactory";
import { ServicePrincipalCredentialProvider } from "./ServicePrincipalCredentialProvider";

/**
* Azure Function triggered by an HTTP request.
* @param {Context} context - The Azure Function context object.
* @param {HttpRequest} req - The HTTP request object.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const accountUrl = process.env.AZURE_STORAGEQUEUE_RESOURCEENDPOINT;
const tenantId = process.env.AZURE_STORAGEQUEUE_TENANTID;
const clientId = process.env.AZURE_STORAGEQUEUE_CLIENTID;
const clientSecret = process.env.AZURE_STORAGEQUEUE_CLIENTSECRET;
const credentialProvider = new ServicePrincipalCredentialProvider(tenantId, clientId, clientSecret);
const queueServiceClientFactory = new QueueServiceClientFactory(accountUrl, credentialProvider);

const queueServiceClient = queueServiceClientFactory.createQueueServiceClient();
const queueClient = queueServiceClient.getQueueClient(queueName);
await queueClient.sendMessage("Hello World!");

context.res = {
status: 200,
body: { text: "menssage sent" }
};
};

export default httpTrigger;

Conclusão

Neste artigo, discutimos como configurar e utilizar Azure Functions para interação com filas do Azure, seguindo os princípios SOLID utilizando Factory Pattern. Ao modularizar a obtenção de credenciais e a criação de clientes de serviço, facilitamos a manutenção e expansão do código em cenários de autenticação diversificados.

Referências

--

--

Cláudio Rapôso
Cláudio Rapôso

Written by Cláudio Rapôso

Microsoft MVP | Software Architect | Teacher | Book Author | MCT | 12x Microsoft Certified Connect with me in https://www.linkedin.com/in/cfraposo