Vamos iniciar este artigo com uma pergunta: Alguma vez você já buscou uma grande quantidade de dados do seu banco, por exemplo, 5000 registros de uma vez, e percebeu uma lentidão na hora da busca? E mais, ficou pensando: “Se está travando aqui, imagine quando for para produção, com milhares de requisições, como a API vai suportar isso tudo?”
Pois bem, isso é algo bastante comum. É normal termos que disponibilizar uma grande quantidade de dados para nossos usuários, ter que buscá-los do banco de dados e retornar a cada requisição. E claro, isso pesa para nossa aplicação. Imagine você, a cada milissegundo, ter que buscar mais de 5000 informações, isso para pessoas diferentes em curtos espaços de tempo.
O que é o cache?
Basicamente, o cache é um mecanismo de acesso rápido, interno de um sistema, que serve de intermediário entre um operador de um processo e o dispositivo de armazenamento ao qual esse operador acessa. De maneira resumida, é uma ótima maneira de carregar dados na memória da aplicação, do lado do servidor.
Isso, por sua vez, nos auxilia no problema comentado acima. Podemos utilizar o cache para armazenar as informações mais pertinentes da nossa aplicação, no caso, a busca de usuários. Podemos definir uma “cacheKey” para armazenar e buscar as informações do cache e retornar para o nosso usuário. Assim, trazemos mais performance para nossa aplicação e evitamos uma consulta no banco de dados (já que, com o cache, as informações estarão na memória da aplicação).
Implementando cache com ASP.NET
Antes de mostrar o código, devemos compreender duas propriedades do cache, a SlidingExpiration e a AbsoluteExpiration. Ambos seguem princípios similares, mas têm suas diferenças. O SlidingExpiration recebe como parâmetro uma quantidade em segundos que representa o intervalo que ele mantém o cache salvo sem receber requisições, por exemplo, 45s. Se nossa aplicação não receber NENHUMA requisição nesse intervalo de tempo, o cache será limpo e recarregado na próxima requisição.
Diferente do SlidingExpiration, o AbsoluteExpiration remove o cache após o intervalo em segundos definido. Ou seja, se colocamos 3600s, após esse tempo, mesmo que ainda haja um número constante de requisições, o nosso cache será limpo e recarregado na próxima requisição.
Ambas as propriedades são extremamente importantes, pois cabe a nós, como desenvolvedores, definir o tempo em que os dados ficarão armazenados em cache. Sempre levando em consideração o contexto, já que, caso tenhamos um número constante de mudanças nos nossos dados, não faz sentido deixar o cache salvo por muito tempo.
Agora, vamos para o código.
Vamos iniciar injetando a interface IMemoryCache do ASP.NET, que será a responsável por nos prover o mecanismo de cache, além de definir a nossa cacheKey para conseguirmos buscar as informações do cache.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
namespace Feedbacks.Controllers
{
[ApiController]
[Route("usuarios")]
public class UsuariosController : ControllerBase
{
private readonly IUsuariosRepository _repository;
private readonly IMemoryCache _cache;
private readonly string userCacheKey = "userCacheKey";
public UsuariosController(IMemoryCache cache, IUsuariosRepository repository)
{
_cache = cache;
_repository = repository;
}
}
}
Agora, basta implementar no nosso controller. Vamos adicionar uma lógica bem simples: primeiro verificamos se a informação existe em cache; caso não exista, configuramos ela e setamos os dados:
[HttpGet]
public async Task<IActionResult> GetAll()
{
if(!_cache.TryGetValue(userCacheKey, out var usuarios))
{
usuarios = await _repository.FindAllAsync();
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(45))
.SetAbsoluteExpiration(TimeSpan.FromSeconds(3600))
.SetPriority(CacheItemPriority.Normal);
_cache.Set(userCacheKey, usuarios, cacheEntryOptions);
}
return Ok(usuarios);
}
Conclusão
Simples, não? Neste artigo, vimos como é fácil implementar um sistema de cache na sua aplicação com o IMemoryCache, além de compreender como isso afeta o desempenho da sua aplicação.