Invalidar una caché con change streams
Borra de Redis las entradas de los productos que cambian, sin perder eventos si el proceso se reinicia.
Si guardas productos en una caché, tienes que borrar cada entrada cuando el producto cambia. Un change stream te avisa de cada cambio en orden de commit, y su token de reanudación evita perder eventos si tu proceso se cae.
El proceso
JavaScript
import { MongoClient } from "mongodb";
import { createClient } from "redis";
const mongo = new MongoClient(process.env.TESELADB_URI);
const redis = createClient({ url: process.env.REDIS_URL });
await Promise.all([mongo.connect(), redis.connect()]);
const db = mongo.db("shop");
const state = db.collection("stream_state");
const saved = await state.findOne({ _id: "product-cache" });
const stream = db
.collection("products")
.watch(
[{ $match: { operationType: { $in: ["update", "replace", "delete"] } } }],
saved ? { resumeAfter: saved.token } : {},
);
for await (const change of stream) {
await redis.del(`product:${change.documentKey._id}`);
await state.updateOne({ _id: "product-cache" }, { $set: { token: change._id } }, { upsert: true });
}Por qué funciona
- El stream entrega los eventos en orden de commit y sin duplicados, aunque los rangos de
productsse dividan o cambien de líder. - Después de borrar la entrada, el proceso guarda el token del evento. Al reiniciar,
resumeAftersigue justo después del último evento tratado. - Si el proceso se cae entre el borrado y el guardado del token, al volver repite ese evento: borrar una clave dos veces no hace daño.
Cuánto tiempo puedes estar parado
Puedes reanudar mientras el evento siga en el historial del clúster: 24 horas por defecto. Si tu proceso puede estar
parado más tiempo, sube teselaHistoryRetention:
JavaScript
db.adminCommand({ setClusterParameter: { teselaHistoryRetention: { seconds: 259200 } } });Si el token es más antiguo que el historial, el stream falla al abrirse. En ese caso vacía la caché entera y empieza un
stream nuevo sin resumeAfter.
Última actualización