Olá pessoal tudo bem?
Iniciaremos através deste post uma série sobre como montar um CRUD completo utilizando a última versão (3) do Azure Functions.
Importante: Para concluirmos o CRUD de maneira satisfatória, vamos precisar instalar as seguintes ferramentas:
- Azure Functions Core Tools
- Visual Studio Code
- Azure Storage Emulator (disponível apenas para Windows)
- Azure Storage Explorer
No Visual Studio Code recomendo fortemente instalar a extensão do Azure Functions, pois ela vai nos ajudar bastante.
Assim que todas as instalações forem concluídas, vamos executar o Azure Storage Emulator (caso o mesmo já não esteja em execução), e então na sequência, vamos criar nosso projeto no Visual Studio Code, abrindo seu Terminal (Ctrl + ‘) e em seguida digitando o seguinte comando:
func init
Feito vão aparecer 4 opções de seleção, nesse caso, selecione a primeira opção “dotnet”, e então, espere que termine a criação do nosso Function App.
Nosso próximo passo será o de criar nossa primeira Azure Function, e para isso digite o comando abaixo:
func new
Feito isso apareceram diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e daremos a ela o nome de CreatePerson.
Abra o arquivo criado (CreatePerson.cs) e observe que ele já veio com um código padrão. Esse código nada mais faz, do que esperar um parâmetro chamado name e no fim exibirá uma mensagem de boas vindas.
Note que a função possui um cabeçalho, e ele e de extrema importância, pois é através dele que “injetaremos” os serviços que desejamos consumir na nossa Function.
Dica 1: Por boas práticas inclusive recomendadas no livro Clean Code do Robert C. Martin (Cap. 3 – Functions), uma Função deve ser extremamente pequena e no caso das Azure Functions isso não é excessão, lembre sempre que se uma Função tiver mais de um propósito, faça uma refatoração da mesma.
Dica 2: Quando suas Azure Functions estiverem publicadas no Azure, caso o plano escolhido seja o Consumption (mais barato), uma função tem tempo limite de 10 minutos para executar, logo já é mais que um bom motivo para suas funções serem “pequenas”.
Voltando para a nossa função CreatePreson vamos substitui o código padrão pelo código abaixo:
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequest req,
[Queue("CreatePerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem,
ILogger log)
{
log.LogInformation("CreatePerson function started a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
await queueItem.AddAsync(requestBody);
log.LogInformation("CreatePerson function finished a request.");
return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}
Observe que o Visual Studio Code vai indicar um erro, na palavra Queue e na propriedade Connection. Isso deve ao fato de que ele não encontrou as mesmas e portanto precisamos importar o SDK do Azure Storage na nossa aplicação, e para fazer isso, abra o arquivo .csproj do seu projeto e logo abaixo da linha em que ele adiciona a referência do SDK das Azure Functions, adicione a seguinte referência:
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="3.0.10" />
Com isso ele vai pedir para fazer o Restore do seu projeto e em seguida os erros deixarão de existir.
Comentando sobre o código da nossa Function, nós basicamente “injetamos” a possibilidade de lidar com as Queues do Azure Storage, e então através da nossa HttpTrigger receberemos o conteúdo contido no body da nossa requisição e então, enfileiraremos esse conteúdo no serviço de mensageria do Azure Storage. Note também, que na propriedade Connection eu passo um valor chamado “AzureWebJobsStorage”, nesse caso, vamos abrir o arquivo local.settings.json e localizar a propriedade “AzureWebJobsStorage” e então, substituir o conteúdo dela para a String de Conexão do nosso Azure Storage Emulator. Caso você possua Mac ou Linux você pode indicar nesse local a String de Conexão do seu Azure Storage no Azure.
Como desejamos fazer um CRUD completo, vou utilizar a classe abaixo (Person.cs) como referência para o nosso cadastro.
using Microsoft.WindowsAzure.Storage.Table;
namespace AzureFunctions
{
public class Person : TableEntity
{
public string Name { get; set; }
public string Email { get; set; }
public Person() { }
}
}
Observe que na classe Person eu já herdo a classe TableEntity para já facilitar a inserção dos nosso dados em um outro serviço do Azure Storage chamado Azure Tables.
Feito isso, vamos testar nosso Function App, e para isso digite o seguinte comando:
func start
Note que ele criou o seguinte endpoint para nós: CreatePerson: [POST] http://localhost:7071/api/CreatePerson e com isso já é possível testar nossa função (para isso recomendo utilizar um Client REST da sua preferência) passando o seguinte body:
{
"name": "Blog do Ericson",
"email": "ericson@email.com"
}
Feito isso abra a ferramenta Microsoft Azure Storage Explorer (instalada previamente no inicio do post) e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada CreatePerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.
Agora nosso próximo passo será desenfileirar a mensagem e salva-la em um banco de dados, e seguindo nosso exemplo esse banco de dados sera o serviço de Tables (banco de dados NoSQL de chave-valor) do Azure Storage.
Vamos então criar uma nova Azure Function, digitando o novamente o comando abaixo:
func new
Feito isso, novamente aparecerão diversas opções de Azure Functions, e dessa vez escolheremos o tipo QueueTrigger e nós daremos a ela o nome de CreatePersonQueue. Após a criação da mesma substitua o código gerado pelo template pelo código abaixo:
public static void Run(
[QueueTrigger("CreatePerson", Connection = "AzureWebJobsStorage")]string queueItem,
[Table("Person")]CloudTable cloudTable,
ILogger log)
{
log.LogInformation($"CreatePersonQueue trigger function started.");
var data = JsonConvert.DeserializeObject<Person>(queueItem);
data.PartitionKey = "Person";
data.RowKey = Guid.NewGuid().ToString();
var tableOperation = TableOperation.Insert(data);
cloudTable.ExecuteAsync(tableOperation);
log.LogInformation($"CreatePersonQueue trigger function finished.");
}
No código acima, vamos deserializar a mensagem para o tipo Person e em seguida precisamos criar duas propriedades obrigatórias para que se possa utilizar o serviço de Tables do Azure Storage. Explicando de maneira bem resumida, a RowKey teria uma função similar ao de um ID de um banco de dados relacional e a PartitionKey teria a função de ajustar o particionamento automático do serviço de Tables do Azure Storage.
Com isso vamos executar nosso Function App novamente através do comando:
func start
E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila, e agora a mesma encontra-se salva na tabela Person (criada automaticamente) dentro do serviço de Tables.
Bom pessoal, e com isso finalizamos a primeira parte do nosso CRUD Serverless em que criamos nosso registro. No nosso próximo post vamos trabalhar na edição e exclusão dele.
E para finalizar deixo aqui um convite.
Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?
Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson
Até mais pessoal.
Abraços e Obrigado!