Pular para o conteúdo

Módulo Cache

O módulo cache fornece um sistema de cache distribuído para scripts Lua. O cache suporta operações de leitura/escrita com expiração automática (TTL) e mecanismos de sincronização para operações concorrentes.

O sistema de cache é especialmente útil para:

  • Armazenar resultados de operações caras (como requisições HTTP, consultas de banco de dados)

  • Evitar chamadas redundantes a APIs externas

  • Sincronizar múltiplos workers que tentam acessar o mesmo recurso simultaneamente

  • Compartilhar dados entre diferentes scripts Lua em execução

Armazena um valor no cache com um tempo de vida específico.

Parâmetros:

  • key (string): Chave única para identificar o valor no cache

  • value (qualquer tipo Lua): Valor a ser armazenado (pode ser string, número, tabela, booleano, etc.)

  • ttl (number): Time To Live em segundos - quanto tempo o valor permanecerá no cache

Valor de retorno:

  • nil em caso de sucesso

  • Lança erro em caso de falha

Exemplo:

-- Armazenar um resultado de API por 5 minutos (300 segundos)
local resultado_api = {status = "ativo", usuarios = 150}
cache.put("status_sistema", resultado_api, 300)
-- Armazenar uma string simples por 1 hora
cache.put("ultima_atualizacao", "2026-01-15T10:30:00Z", 3600)
-- Armazenar um número
cache.put("contador_requisicoes", 42, 60)

Recupera um valor do cache.

Parâmetros:

  • key (string): Chave do valor a ser recuperado

Valor de retorno:

  • O valor armazenado se existir e não estiver expirado

  • nil se a chave não existir ou o valor tiver expirado

Exemplo:

-- Recuperar um valor do cache
local status = cache.get("status_sistema")
if status then
print("Status do sistema:", status.status)
print("Usuários ativos:", status.usuarios)
else
print("Cache expirado ou não encontrado")
-- Fazer uma nova requisição para obter os dados
end
-- Verificar se um valor existe
local ultima_atualizacao = cache.get("ultima_atualizacao")
if ultima_atualizacao then
print("Última atualização:", ultima_atualizacao)
end

Marca uma chave como “pendente”. Esta função é usada para sincronizar múltiplos workers que tentam calcular o mesmo valor simultaneamente.

Parâmetros:

  • key (string): Chave a ser marcada como pendente

Valor de retorno:

  • nil em caso de sucesso

  • Lança erro em caso de falha

Comportamento:

  • Quando uma chave é marcada como pendente, qualquer chamada subsequente a cache.get() para essa chave irá bloquear até que um valor seja armazenado com cache.put()

  • O estado “pendente” expira automaticamente após 5 minutos (300 segundos)

  • Útil para evitar que múltiplos workers recalculem o mesmo valor caro simultaneamente

Exemplo:

-- Padrão típico para evitar cache stampede
local function obter_dados_caros(chave)
-- Primeiro tenta obter do cache
local dados = cache.get(chave)
if dados then
return dados
end
-- Se não encontrou, marca como pendente
local sucesso, erro = pcall(cache.mark_pending, chave)
if not sucesso then
-- Outro worker já marcou como pendente, espera pelo resultado
dados = cache.get(chave) -- Esta chamada irá bloquear até o valor estar disponível
if dados then
return dados
end
end
-- Este worker é responsável por calcular o valor
-- ... cálculo caro aqui ...
local resultado = calcular_dados_caros()
-- Armazena no cache para outros workers
cache.put(chave, resultado, 300)
return resultado
end

Remove uma chave do cache imediatamente.

Parâmetros:

  • key (string): Chave a ser removida

Valor de retorno:

  • nil em caso de sucesso

  • Lança erro em caso de falha

Exemplo:

-- Remover um valor específico
cache.delete("dados_expirados")
-- Limpar cache relacionado a um usuário
cache.delete("usuario_123_perfil")
cache.delete("usuario_123_preferencias")
cache.delete("usuario_123_historico")

O mecanismo de “pendente” permite que múltiplos workers sincronizem o cálculo de valores caros:

  1. Primeiro worker marca a chave como pendente e calcula o valor

  2. Outros workers que tentam acessar a mesma chave aguardam o resultado

  3. Quando o primeiro worker termina, armazena o valor e todos os workers recebem

O cache pode armazenar qualquer tipo de valor Lua suportado pelo sistema de serialização do Monsta, incluindo:

  • Strings

  • Números

  • Booleanos

  • Tabelas

  • Valores nulos

  1. Acesso rápido: Operações de cache são muito mais rápidas que recalcular valores ou fazer requisições externas

  2. Memória: O cache é mantido em memória, então valores muito grandes podem impactar a performance

  3. Concorrência: O sistema é thread-safe e suporta acesso concorrente de múltiplos workers

  4. Network: O cache é local ao processo, não há overhead de rede

  1. Volátil: Dados são perdidos se o processo for reiniciado

  2. Memória limitada: Não use para armazenar grandes volumes de dados

  3. Distribuição: Este é um cache local, não distribuído entre múltiplos servidores

  1. TTL adequado: Use TTLs apropriados para o tipo de dado (curto para dados dinâmicos, longo para dados estáticos)

  2. Chaves descritivas: Use nomes de chave que descrevam claramente o conteúdo

  3. Namespace: Use prefixos para organizar chaves (ex: api_, user_, config_)

  4. Fallback: Sempre tenha um fallback caso o cache esteja vazio ou expirado

  5. Invalidação: Use delete() para invalidar cache quando dados mudarem