Caching
O template implementa caching em multiplas camadas para otimizar performance no Cloudflare Workers.
:::info Nova engine
A partir da versao atual, dados de API (brand, jogos, stats) sao gerenciados pelo @cactus-agents/platform-cache, substituindo o antigo ServerCache manual. A politica de cache e configurada no front-ops e injetada como PLATFORM_CACHE_POLICY_JSON em deploy-time. Veja SDK > platform-cache para detalhes.
:::
Camadas de cache
Requisicao do usuario
|
v
[1] Worker Middleware — SSR response cache (edge, 60s)
|
v
[2] platform-cache engine — dados de API (memory + CF Cache API + KV)
| - brandConfig: TTL 3600s
| - homeRows: TTL 300s
| - gamesBase: TTL 300s
| - gameStats/gameDetail: TTL 300s
v
Backend API
Camada 1 — SSR Response Cache (Worker Middleware)
Cacheia respostas HTML de SSR no edge da Cloudflare para visitantes anonimos.
Regras
| Condicao | Comportamento |
|---|---|
| Metodo != GET | BYPASS |
Path comeca com /api/ ou /proxy/ | BYPASS |
Cookie jwt_token presente | BYPASS (usuario autenticado) |
| Demais | CACHE (HTML) |
Politica
- Fresh:
s-maxage=60(1 minuto) - Stale:
stale-while-revalidate=300(5 minutos) - Header
X-Cache:HIT,MISSouBYPASS
Smartico Proxy
O middleware tambem proxeia /proxy/smartico.js:
- Origem:
https://libs.s.cactusgaming.net/scactus.js - Cache:
s-maxage=3600, stale-while-revalidate=86400(1h fresh, 24h stale) - CORS:
Access-Control-Allow-Origin: *
Em dev, o plugin vite-plugins/dev-proxy-mirror.ts espelha a rota /proxy/smartico.js no Vite dev middleware — o worker não executa em dev. Manter o upstream em sincronia com workers/middleware.ts.
Brands devem apontar gamificationConfig.smartico.libraryUrl pra /proxy/smartico.js (em vez de direto pra libs.s.cactusgaming.net) pra manter a URL same-origin no HTML e aproveitar o cache edge.
Camada 2 — platform-cache engine
O @cactus-agents/platform-cache substitui o antigo ServerCache manual. E criado no loader SSR com base na PLATFORM_CACHE_POLICY_JSON injetada pelo front-ops:
import { createCacheEngine, parseCachePolicy, CacheApiStore, NoopSnapshotStore } from "@cactus-agents/platform-cache";
const engine = createCacheEngine({
policy: parseCachePolicy(env.PLATFORM_CACHE_POLICY_JSON),
primaryStore: new CacheApiStore(),
snapshotStore: env.PLATFORM_CACHE_KV
? new KvSnapshotStore(env.PLATFORM_CACHE_KV)
: new NoopSnapshotStore(),
domain: env.ORIGIN_DOMAIN,
});
Quando PLATFORM_CACHE_POLICY_JSON esta ausente (dev local), o engine opera em modo bypass — todas as requisicoes vao direto para a API, sem cache.
ServerCache (legado — mantido para referencia)
O ServerCache manual ainda existe nos arquivos do template para o SSR response cache e casos de uso legacy nao migrados.
Classe base para cache server-side de 2 niveis:
Niveis
- In-memory (Map no isolate do Worker) — hit instantaneo, compartilhado dentro do mesmo isolate
- CF Cache API (
caches.default) — compartilhado entre isolates, persiste alem do lifecycle do Worker
Lookup
get(key)
|
├── [memory] fresh → retorna
├── [memory] stale → retorna (marcado como stale)
├── [CF Cache] hit → retorna + popula memory
└── miss → retorna null
Status
fresh— dentro do TTLstale— fora do TTL mas dentro do grace periodmiss— nao encontrado
Instancias globais
| Factory | Namespace | TTL | Stale Grace |
|---|---|---|---|
getBrandCache() | brand | 3600s (1h) | 3600s |
getGamesCache() | games | 300s (5min) | 300s |
Camada 3 — GamesCacheService
Wrapper domain-specific sobre ServerCache para dados de jogos. Usa stale-while-revalidate com waitUntil() para revalidacao nao-bloqueante.
Padrao stale-while-revalidate
get(key)
|
├── fresh → retorna imediatamente
├── stale → retorna imediatamente + ctx.waitUntil(revalidate())
└── miss → fetch da API + cache + retorna
A revalidacao em background usa waitUntil() do Cloudflare Workers para nao bloquear a resposta.
Chaves de cache
O formato e {domain}/{segment}:
| Metodo | Chave | Descricao |
|---|---|---|
getHome() | mybrand.com/home | Layout da homepage |
getBase() | mybrand.com/base | Categorias + providers |
getAllGames() | mybrand.com/all-games | Todos os jogos (agregado) |
getByCategory(slug) | mybrand.com/category/slots | Jogos por categoria |
getByProvider(slug) | mybrand.com/provider/pragmatic | Jogos por provider |
getDetail(slug) | mybrand.com/game/sweet-bonanza | Detalhe de jogo |
search(params) | usa all-games | Filtro in-memory sobre cache |
Busca
A busca de jogos nao faz request na API. Usa o cache de all-games e filtra in-memory via filterGames() do SDK — rapido e sem latencia de rede.
Purge
Via API route
POST /api/cache/games/purge
POST /api/dev/cache-clear
Programatico
import { purgeAllCaches, getAllCacheStats } from "~/services/cache.server";
// Purge tudo
await purgeAllCaches();
// Stats
const stats = getAllCacheStats();
// { brand: { hits, misses, ... }, games: { ... } }
Env vars
| Variavel | Descricao |
|---|---|
PLATFORM_CACHE_POLICY_JSON | Politica serializada — injetada pelo front-ops em deploy-time. Ausente em dev local = bypass. |
PLATFORM_CACHE_KV | Binding KV para snapshots (provisionado automaticamente pelo front-ops). |
CACHE_PURGE_SECRET | Secret para o endpoint POST /api/cache/games/purge. |
Arquivos
| Arquivo | Descricao |
|---|---|
workers/middleware.ts | SSR response cache + Smartico proxy |
services/cache.server.ts | ServerCache base + factories (legacy) |
services/games.cache.server.ts | GamesCacheService (legacy, sendo substituido por platform-cache) |