Photo by Oskar Yildiz on Unsplash

Conhecendo o External Configuration Store Pattern: Parte 3 - Criando o Client

Rafael Capuano
Jun 17 · 3 min read

Na parte anterior desta série, vimos como criar a API do Configuration. Agora é hora de apresentar o Client para fazer as requisições. Para isso, foi utilizado um projeto do tipo Class Library do .NET Core. Esse projeto poderia ser disponibilizado via NuGet, por exemplo, sendo dessa forma, o meio de acesso das aplicações à API do Configuration, encapsulando toda a lógica para construção das requisições, como o cache e a autenticação.

Primeiro, foi definida a classe CacheItem que guardará o valor de cache, bem como o seu período de validade:

A interface ICacheItemFactory define uma estrutura para criação do dicionário que conterá os itens a serem armazenados em cache:

A seguir, temos a implementação por meio da classe CacheItemFactory:

Na sequência, temos a definição da interface ICacheManager que será o meio de acesso a esses valores:

Agora, a implementação através da classe CacheManager que define um período simbólico de trinta minutos de validade para o valor em cache:

Como dito anteriormente, a ideia é que esse código possa ser disponibilizado como um pacote NuGet. Uma possibilidade de implementação é aproveitar o comportamento “plugável” do .NET Core, onde temos o método ConfigureServices(), responsável pela regra de injeção de dependência da classe Startup. Pensando nisso, foi criada uma extension class, ConfigurationEntension, encapsulando as dependências do nosso Client:

Bom, se olharmos cada uma das linhas, teremos componentes já conhecidos, como ICacheManager e o ICacheAccessToken, os demais serão apresentados na sequência. A próxima etapa é a autenticação. Primeiro, temos a interface IAuthenticationClient:

A seguir, temos a implementação através da classe AuthenticationClient:

Essa classe é responsável por obter o access token para acesso ao Configuration, para isso, novamente fazemos uso do NuGet IdentityServer4.AccessTokenValidation. Uma vez obtido, ele também é armazenado em um cache. Esse cache, porém, é próprio para o token. A interface ICacheAccessToken é apresentada a seguir:

Na sequência, temos a implementação pela classe CacheAccessToken:

Conforme visto antes, quando um valor do Configuration é atualizado, devemos atualizar o nosso cache. Estamos utilizando o RabbitMQ para nos auxiliar nesse processo, portanto, seguindo essa ideia, o nosso Client precisa estar preparado para receber as mensagens enviadas através dele.

Para que isso seja é possível, foi criada a classe SubscribeService. Ela funciona como uma execução em segundo plano que fica “ouvindo” os eventos lançados através do RabbitMQ. Quando uma nova mensagem é recebida, significa que o valor do cache deve ser atualizado. Para isso, novamente fazemos uso do NuGet RabbitMQ.Client:

Mas como fazemos para enviar o token de autenticação? Para realizar essa etapa, tiramos proveito da classe DelegatingHandler. A ideia é interceptar as requisições realizadas por meio de um objeto HttpClient. Isso permitirá encapsular essa lógica. Basicamente, a classe AccessTokenHandler obtém o token (que pode já estar em cache) e o envia no header da nossa requisição:

Agora, vamos dar uma olhada na classe que será executada para chamar o Configuration. Primeiro temos a interface IConfigurationClient:

Na sequência, temos a implementação através da classe ConfigurationClient. Observe como essa classe faz uso de um objeto HttpClient, o que fará ser executado o código do AccessTokenHandler no momento da requisição:

Como a ideia é disponibilizar o ConfigurationClient como um NuGet, vamos simular esse processo. Após criar um novo projeto Web e instalar o pacote, na nova classe Startup, dentro de ConfigureServices(), bastaria chamar AddConfigurationClient() passando o endereço da API do Configuration:

Isso já daria acesso à implementação da interface IConfigurationClient em qualquer outra classe da aplicação. Olha só o exemplo a seguir:


Concluindo

Outros recursos ainda poderiam ser adicionados ao nosso NuGet, como o gerenciamento de logs e um tratamento para resiliência, por exemplo. Apesar disso, espero que este artigo tenha demonstrado a base da ideia do External Configuration Store Pattern, bem como as diversas possibilidades de implementação.

Bom, vamos ficando por aqui. Espero que tenham gostado do conteúdo.

Obrigado e bom código!

Rafael Capuano

Written by

Analista de Sistemas na Praxio Tecnologia