🚀 Implementando cache em uma API utilizando Design Pattern (Redis + Proxy)
Fala pessoal, tudo blz? Hoje venho compartilhar um pouco do que venho estudando ultimamente. Trata-se de uma implementação simples de um sistema de cache no backend utilizando o banco Redis, seguindo a estrutura do design pattern Proxy.
Antes de apresentar o código do projeto, vamos entender um pouco acerca das tecnologias que foram utilizadas.
O que é cache
Cache, ou memória cache, trata-se de um armazenamento de acesso rápido utilizado por computadores e smartphones para guardar arquivos temporários que são acessados com frequência.
Caso deseje entender melhor sobre esse assunto, acesse o post onde explico de forma mais detalhada e com analogias o funcionamento do cache.
Utilizando cache no backend com o Redis
Utilizamos a estratégia de cache para aumentar a performance das requisições da nossa aplicação. Iremos utilizar o Redis (banco de dados open-source) como memória cache nesse exemplo devido a sua rápida resposta a requisições de leitura.
O padrão proxy
Na implementação do cache, iremos utilizar o design pattern Proxy. Isso permitirá que o Redis atue como um intermediário entre o código e o banco de dados principal da aplicação (nesse exemplo, para fins de práticidade, será o SQLite junto com o Prisma). Dessa forma, antes de solicitarmos algum dado ao banco, iremos checar se esse mesmo dado se encontra em cache, ou seja, salvo no Redis.
Caso deseje ver mais detalhes sobre o padrão Proxy, recomendo assistir o vídeo, que fiz sobre o assunto e também dar uma lida na página do Proxy, no site do Refactoring Guru.
Aplicando na prática
Não irei mostrar o código completo aqui, apenas a classes principais que implementam a estratégia de cache. Caso deseje ver o código-fonte completo (com algumas modificações), acesse o repositório da aplicação, ou então veja o vídeo que fiz desenvolvendo esse projeto.
- Repository principal (SQLite)
export class PrismaUserRepository implements UserRepository {
constructor(
private readonly prisma: PrismaService
) {}
async findMany() {
const users = await this.prisma.user.findMany()
return users;
}
}
- Implementação do Proxy (Redis como intermediário entre código e SQLite)
export class RedisUserRepository implements UserRepository {
constructor(
private readonly redis: RedisService,
private readonly prismaUserRepository: PrismaUserRepository,
) {}
async findMany() {
// Verificar se os dados já estão em cache
const cachedUsers = await this.redis.get('users');
// Caso não estejam, buscar os dados no banco principal
// e em seguida salvá-los no cache
if (!cachedUsers) {
const users = await this.prismaUserRepository.findMany();
// Salvando no cache com expiração de 15 segundos
await this.redis.set('users', JSON.stringify(users), 'EX', 15);
return users;
}
// Caso estejam, retornar os dados em cache
return JSON.parse(cachedUsers);
}
}
Espero que tenha curtido! Fique a vontade para deixar seu feedback!