Saltar al contenido
Chatbots de WhatsApp desde cero
Temario

Ejercicio: Memoria con Cloudflare KV

  • ⏱ 45 minutos
  • 📶 Nivel: intermedio

Objetivo

Entender cómo se guarda y se olvida la memoria del bot: ponerle nombre a las claves, decidir cuánto vive cada dato y comprobar con un KV de mentira (que corre en tu navegador) qué pasa cuando pasa el tiempo.

Cómo se trabaja

La parte A es práctica real en tu terminal con el Worker del curso. La parte B son funciones de JavaScript puro que se comprueban en esta página. Los tiempos se manejan en segundos (para el TTL) y en milisegundos (para el reloj), igual que en worker.js.

💡 Reto extra

Añade renovar(kv, clave) que relea un valor y lo vuelva a guardar con su TTL completo. Así modelas lo que hace el Worker cada vez que el cliente escribe: la sesión se «renueva» y solo se olvida a quien lleva dos días en silencio.

▶ Prueba tu código aquí (opcional)
Consola

Pasos

Marca cada paso a medida que lo completes. Tu avance se guarda en este navegador.

💡 Pista 1: Dejar solo dígitos

telefono.replace(/\D/g, "") quita todo lo que no sea un dígito. Comprueba el resultado antes de armar la clave.

💡 Pista 2: Cuándo vence una clave

Al guardar, calcula vence = ahora() + ttl * 1000. Al leer, si ahora() >= vence, devuelve null (y puedes borrar la entrada del Map).

💡 Pista 3: Idempotencia con visto:

Usa la clave "visto:" + idMensaje. Si kv.get(clave) no es null, devuelve false. Si es null, guarda "1" con ttlPara(clave) y devuelve true.

🔎 Comprueba tu trabajo

Pega tu código y pulsa Comprobar. La revisión ocurre en tu navegador; nada se envía a ningún sitio. Cada punto en rojo incluye una pista. Pega solo el JavaScript, sin las etiquetas <script>.

    ✅ Ver una solución posible

    Intenta resolverlo antes de mirar. Tu versión puede ser distinta y también correcta.

    funciones.js
    function claveSesion(telefono) {
      const digitos = String(telefono).replace(/\D/g, "");
      if (!digitos) throw new Error("Teléfono sin dígitos");
      return "sesion:" + digitos;
    }
    
    const DIA = 24 * 60 * 60;
    
    function ttlPara(clave) {
      if (clave.startsWith("sesion:")) return 2 * DIA;
      if (clave.startsWith("pedido:")) return 30 * DIA;
      if (clave.startsWith("visto:")) return DIA;
      throw new Error("Prefijo sin TTL definido: " + clave);
    }
    
    function crearKvFalso(ahora) {
      const datos = new Map();
      return {
        put(clave, valor, ttlSegundos) {
          datos.set(clave, { valor, vence: ahora() + ttlSegundos * 1000 });
        },
        get(clave) {
          const entrada = datos.get(clave);
          if (!entrada) return null;
          if (ahora() >= entrada.vence) { datos.delete(clave); return null; }
          return entrada.valor;
        },
      };
    }
    
    function idempotente(kv, idMensaje) {
      const clave = "visto:" + idMensaje;
      if (kv.get(clave) !== null) return false;
      kv.put(clave, "1", ttlPara(clave));
      return true;
    }