Gestionar actualizaciones de configuración retrasadas

CloudflareBeginner
Practicar Ahora

Introducción

Un centro de ayuda puede leer su tema y su banner de bienvenida desde KV, de modo que un editor pueda cambiar esos ajustes sin implementar código nuevo. Después de una actualización, los lectores de distintas ubicaciones pueden ver brevemente versiones diferentes. La aplicación debe seguir siendo utilizable durante esa transición, en lugar de asumir que cada lectura devuelve los ajustes más recientes.

Usted creará un lector de configuración versionado con valores predeterminados seguros, probará una secuencia simulada deliberadamente con valores antiguos y nuevos y, después, realizará una actualización real en la nube. Una versión es una etiqueta almacenada junto con los ajustes; le ayuda a identificar el valor recibido. No convierte KV en una base de datos fuertemente consistente ni garantiza que las solicitudes sucesivas vean números de versión crecientes.

Complete primero los laboratorios anteriores sobre KV. Esta VM independiente tiene Node.js 22.22.0 y Wrangler 4.131.1 instalado localmente en el proyecto /home/labex/project/delayed-config. Utilice su propia cuenta de aprendizaje con los mismos permisos de lectura de cuenta, escritura de Workers y escritura de KV. El ejercicio crea un Worker y un espacio de nombres desechables, y solo expone ajustes de presentación sintéticos. No se necesita una actualización de pago ni un dominio adquirido para este pequeño conjunto de datos. Estos ajustes no controlan la autorización, los pagos ni otras decisiones que requieran una actualización autorizada inmediata.

Conectar un almacén de configuración independiente

En este paso, conectará un espacio de nombres nuevo para la configuración de presentación. El binding CONFIG mantiene la referencia al recurso en la configuración estándar de Wrangler. Utilice recursos nuevos del laboratorio para que los ajustes deliberadamente no válidos no afecten a otra aplicación.

Entre en el proyecto preparado:

cd /home/labex/project/delayed-config

Genere un nombre único una sola vez. openssl rand -hex 6 muestra un sufijo aleatorio; $(...) lo inserta en el nombre. La variable de shell mantiene ese nombre disponible para los comandos siguientes en este terminal.

WORKER_NAME="labex-config-$(openssl rand -hex 6)"
printf '%s\n' "$WORKER_NAME"

Autorice esta VM. Además de leer la identidad de su cuenta, Workers Scripts Write permite implementar y eliminar recursos, y Workers KV Write permite administrar el espacio de nombres y las claves de este laboratorio.

npx wrangler login --device --browser=false --scopes account:read user:read workers_scripts:write workers_kv:write

Abra en su navegador el enlace del dispositivo que aparece, introduzca el código actual, revise los permisos solicitados y la cuenta de aprendizaje, y autorice Wrangler. En la página de consentimiento también puede aparecer el acceso en segundo plano. Vuelva al terminal y espere a que finalice el inicio de sesión.

Revise los mismos permisos de escritura de Worker y KV presentados anteriormente en este curso, y confirme la cuenta de aprendizaje.

npx wrangler whoami --json

Confirme loggedIn: true y el name de la cuenta de aprendizaje, aunque solo aparezca una cuenta. Copie el id de esa cuenta. Guárdelo en la configuración siguiente, sustituyendo YOUR_ACCOUNT_ID antes de ejecutar el comando. El documento here-document de cat escribe en un archivo todo lo que se encuentra entre las dos líneas JSON; > reemplaza el archivo. El delimitador sin comillas permite que el shell inserte $WORKER_NAME.

cat > wrangler.jsonc <<JSON
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-07-30",
  "account_id": "YOUR_ACCOUNT_ID",
  "workers_dev": true
}
JSON

Cree un espacio de nombres en esa cuenta. Su título comparte el nombre único del Worker para que pueda reconocer ambos recursos más adelante. --update-config=false deja visible para usted la edición del binding, en lugar de cambiar el archivo automáticamente.

npx wrangler kv namespace create "$WORKER_NAME-config" --update-config=false

La salida incluye el ID del nuevo espacio de nombres. Cópielo y, después, sustituya YOUR_ACCOUNT_ID y YOUR_NAMESPACE_ID en esta configuración completa. El nombre del binding CONFIG lo elige su código; el ID identifica el recurso real de Cloudflare.

cat > wrangler.jsonc <<JSON
{
  "name": "$WORKER_NAME",
  "main": "src/index.js",
  "compatibility_date": "2026-07-30",
  "account_id": "YOUR_ACCOUNT_ID",
  "workers_dev": true,
  "kv_namespaces": [
    { "binding": "CONFIG", "id": "YOUR_NAMESPACE_ID" }
  ]
}
JSON
npx wrangler kv namespace list

Busque el título del espacio de nombres de este laboratorio y compare su ID con el del archivo. Puede haber otros espacios de nombres; no los modifique. Esta configuración registra qué cuenta y qué recurso deben utilizar los comandos posteriores. Un binding es una referencia a un espacio de nombres, no una copia de sus datos.

Leer ajustes versionados con valores predeterminados seguros

En este paso, permitirá que ambas versiones válidas produzcan respuestas utilizables. Si faltan los ajustes de presentación o están dañados, se utilizará un tema claro sencillo y ningún banner. Así, un ajuste de presentación opcional no impedirá que funcione el centro de ayuda.

Escriba el handler. El objeto defaults fijo no contiene estado específico de la solicitud y nunca se modifica. Cada solicitud lee su propio resultado de KV.

cat > src/index.js <<'JS'
const defaults = { version: 0, theme: "light", banner: "", source: "default" };

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname === "/health") return Response.json({ status: "ok" });
    const key = url.searchParams.get("key") ?? "config:current";
    if (url.pathname !== "/settings" || !/^config:[a-z0-9-]{1,20}$/.test(key)) {
      return new Response("Not found", { status: 404 });
    }
    let value;
    try {
      value = await env.CONFIG.get(key, { type: "text", cacheTtl: 60 });
    } catch {
      return Response.json({ error: "Settings temporarily unavailable" }, { status: 503 });
    }
    if (value === null) return Response.json(defaults);
    let settings;
    try {
      settings = JSON.parse(value);
    } catch {
      return Response.json(defaults);
    }
    if (!settings || !Number.isSafeInteger(settings.version) || settings.version < 1 ||
        !["light", "dark"].includes(settings.theme) ||
        typeof settings.banner !== "string" || settings.banner.length > 80) {
      return Response.json(defaults);
    }
    return Response.json({
      version: settings.version, theme: settings.theme,
      banner: settings.banner, source: "stored"
    });
  }
};
JS

La solicitud a KV utiliza cacheTtl: 60, una duración de caché de lectura expresada en segundos. Esto no caduca la clave almacenada. Tampoco indica que cada ubicación deba obtener por la fuerza el valor más reciente. Tanto los valores existentes como los resultados de claves inexistentes pueden almacenarse en caché. Mantenga las escrituras poco frecuentes y diseñe la aplicación para tolerar una configuración válida más antigua.

El handler valida la versión, el tema admitido y la longitud del banner antes de utilizarlos. La ruta /health responde sin leer los ajustes opcionales. Un error de almacenamiento sigue produciendo un 503 explícito en /settings; la aplicación no informa falsamente que cargó correctamente los valores predeterminados desde el almacenamiento.

Cree dos archivos pequeños de versión. Mantener cada valor previsto en un archivo normal facilita su inspección antes de escribirlo:

cat > config-v1.json <<'JSON'
{"version":1,"theme":"light","banner":"Welcome"}
JSON
cat > config-v2.json <<'JSON'
{"version":2,"theme":"dark","banner":"New help center"}
JSON

Escríbalos en claves de prueba locales independientes, junto con un valor con formato incorrecto. Estas claves hacen reproducibles las entradas posibles; no simulan la temporización de la red de Cloudflare.

npx wrangler kv key put config:v1 --path config-v1.json --binding CONFIG --local
npx wrangler kv key put config:v2 --path config-v2.json --binding CONFIG --local
npx wrangler kv key put config:broken broken-json --binding CONFIG --local
npx wrangler dev --local --ip 0.0.0.0 --port 8080 > local.log 2>&1 &
DEV_PID=$!
cat local.log

Espere el mensaje de que el servidor está listo. Después, compare las dos claves seleccionadas explícitamente:

curl -i 'http://127.0.0.1:8080/settings?key=config:v1'
curl -i 'http://127.0.0.1:8080/settings?key=config:v2'

Ambas devuelven HTTP 200 con source: "stored". La versión 1 es clara y contiene Welcome; la versión 2 es oscura y contiene New help center. Ninguna versión depende del resultado de una solicitud anterior.

curl -i 'http://127.0.0.1:8080/settings?key=config:missing'
curl -i 'http://127.0.0.1:8080/settings?key=config:broken'

Ambas deben devolver {"version":0,"theme":"light","banner":"","source":"default"}. La versión 0 es la etiqueta predeterminada de la aplicación; no es una revisión almacenada en KV.

curl -i http://127.0.0.1:8080/health

Espere {"status":"ok"}. Mantenga el servidor local en ejecución hasta la limpieza.

Probar una secuencia controlada de lecturas antiguas

En este paso, probará el handler con una secuencia predecible: antigua, nueva, antigua de nuevo, nueva, inexistente y no válida. Esto es un accesorio de prueba, es decir, una entrada proporcionada deliberadamente para repetir una situación que, de otro modo, sería impredecible. No demuestra que una solicitud real de Cloudflare haya sido obsoleta.

Cree una prueba pequeña de Node.js con la biblioteca de aserciones estándar. Importa el handler que escribió y proporciona la misma interfaz CONFIG.get() con valores de retorno controlados:

cat > test-config.mjs <<'JS'
import assert from "node:assert/strict";
import worker from "./src/index.js";

const older = JSON.stringify({ version: 1, theme: "light", banner: "Welcome" });
const newer = JSON.stringify({ version: 2, theme: "dark", banner: "New help center" });
// A controlled fixture: these values simulate different reads, not a cloud outage.
const values = [older, newer, older, newer, null, "broken-json"];
const expectedVersions = [1, 2, 1, 2, 0, 0];
for (let i = 0; i < values.length; i += 1) {
  const env = { CONFIG: { get: async () => values[i] } };
  const response = await worker.fetch(new Request("https://example.test/settings"), env);
  assert.equal(response.status, 200);
  const body = await response.json();
  assert.equal(body.version, expectedVersions[i]);
  assert.ok(["light", "dark"].includes(body.theme));
  assert.equal(typeof body.banner, "string");
}
console.log("Controlled old/new/missing/invalid reads stayed usable.");
JS
node test-config.mjs

Espere Controlled old/new/missing/invalid reads stayed usable. Si una aserción falla, el comando se detiene y muestra un error. La repetición del valor antiguo es intencionada: no añada una variable global del proceso como "latest version" para ocultarla. Los Workers pueden ejecutarse en distintas instancias, por lo que una variable de ese tipo no puede establecer la versión más reciente para toda la cuenta.

Una actualización de configuración debe mantener utilizables las lecturas válidas antiguas durante la transición. Este enfoque es apropiado para un banner o un tema. No haría que KV fuera adecuado para revocar inmediatamente el acceso de una persona. La prueba real en la nube viene a continuación; puede mostrar el valor nuevo en la primera solicitud, y ese es un resultado válido.

Implementar y establecer la primera versión en la nube

En este paso, establecerá una línea base remota real antes de cambiarla. En el espacio de nombres de la nube de este laboratorio solo deben estar la configuración actual y el accesorio de reserva con formato incorrecto.

npx wrangler kv key put config:current --path config-v1.json --binding CONFIG --remote
npx wrangler kv key put config:broken broken-json --binding CONFIG --remote
npx wrangler deploy

Confirme el nombre único del Worker y el binding CONFIG, y copie la URL pública real:

WORKER_URL="https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev"
curl -i "$WORKER_URL/settings"

Espere la versión 1, el tema light, el banner Welcome y source: "stored". Si es necesario, tenga en cuenta el tiempo de disponibilidad del nombre de host y de visibilidad de KV; un error de red no es una respuesta de configuración. Ejecute la comprobación independiente de este paso antes de reemplazar la versión 1. Esta comprobación verifica la cuenta seleccionada, el valor almacenado, el binding implementado, los valores predeterminados y la respuesta de estado.

Observar una actualización real sin exigir una lectura antigua

En este paso, actualizará la configuración almacenada sin modificar el código del Worker. Inspeccione el nuevo valor previsto y, después, escríbalo en la misma clave remota:

cat config-v2.json
npx wrangler kv key put config:current --path config-v2.json --binding CONFIG --remote
npx wrangler kv key get config:current --binding CONFIG --remote --text

La lectura de administración debe contener la versión 2. Ahora inspeccione lo que ve la aplicación:

curl -i "$WORKER_URL/settings"

Puede ver la versión 2 de inmediato o una versión anterior válida mientras las lecturas convergen. No exija una respuesta obsoleta para «demostrar» la consistencia eventual ni vuelva a escribir rápidamente la clave para provocarla. Si es necesario, repita la solicitud HTTP en intervalos de 15 segundos durante un máximo de cinco minutos. Este es un periodo de observación limitado para el ejercicio, no una promesa de que todas las ubicaciones globales convergerán en cinco minutos.

Continúe cuando el endpoint devuelva {"version":2,"theme":"dark","banner":"New help center","source":"stored"}. Si no converge durante ese periodo de observación, compruebe la cuenta y el binding, e informe de un resultado no concluyente. La comprobación independiente requiere que la versión almacenada real y la respuesta real coincidan; un archivo local o un accesorio de prueba no es suficiente.

curl -i "$WORKER_URL/settings?key=config:broken"
curl -i "$WORKER_URL/health"

La configuración de presentación dañada sigue teniendo un valor predeterminado controlado y el estado continúa siendo ok. En el Dashboard, seleccione la misma cuenta e inspeccione el espacio de nombres de este laboratorio en Storage & databases → Workers KV. Compare config:current con la versión 2 de su archivo. Esta vista de solo lectura muestra el valor administrado; no puede demostrar qué tiene actualmente almacenado en caché cada ubicación remota.

La prueba controlada cubrió la tolerancia a valores antiguos, mientras que esta actualización real cubrió la implementación y la convergencia observada en el endpoint de prueba. Mantenga separadas esas conclusiones. Consulte cómo funciona KV para conocer su modelo de consistencia.

Selecciona KV Pairs y después View junto a config:current. Usa Refresh si la lista aún no refleja la actualización. El ejemplo muestra la versión 2, el tema dark y el banner New help center; el nombre generado de tu espacio de nombres será distinto. No cambies el valor en esta comprobación.

Configuración de la versión 2 en el Dashboard

Eliminar los recursos desechables de la nube

En este paso, eliminará ambos recursos mientras Wrangler siga autorizado. Un espacio de nombres puede sobrevivir a su Worker, por lo que eliminar únicamente la aplicación no limpia sus datos.

Detenga el proceso de desarrollo local iniciado en este terminal:

kill "$DEV_PID"

Inspeccione las referencias de recursos guardadas antes de eliminar nada:

cat wrangler.jsonc

Confirme el nombre del Worker labex-config-... y el ID del espacio de nombres CONFIG. Elimine el Worker seleccionado por esta configuración:

npx wrangler delete

Si se le solicita confirmación, compruebe que el nombre mostrado coincide con el de este laboratorio y confirme con y. Después, elimine únicamente el espacio de nombres referenciado por CONFIG:

npx wrangler kv namespace delete --binding CONFIG

Revise el espacio de nombres en cualquier solicitud de confirmación antes de aceptar. Mantenga intacto wrangler.jsonc para que la comprobación independiente pueda identificar los recursos que deberían estar ausentes.

npx wrangler kv namespace list

El espacio de nombres de este laboratorio debe haber desaparecido; los espacios de nombres no relacionados deben permanecer. Actualice las listas del Dashboard para confirmar que el Worker y el espacio de nombres del laboratorio han desaparecido. Una solicitud fallida o una sesión caducada no demuestra que se hayan eliminado. Ejecute la comprobación de este paso antes de cerrar la sesión para que pueda inspeccionar un inventario autorizado.

Finalizar la autorización de la VM

En este paso, desconectará Wrangler después de que la comprobación de limpieza se haya completado correctamente. Cerrar la sesión finaliza la autorización de Wrangler guardada en esta VM; no elimina recursos de la nube ni cierra la sesión de su sesión normal del Dashboard en el navegador.

npx wrangler logout
npx wrangler whoami --json

Confirme que el resultado estructurado informa "loggedIn": false. Este comando sin autenticación puede finalizar con un código de salida distinto de cero, lo cual es esperado en este caso. Si solo aparece un error de conexión y no un estado explícito de autenticación, vuelva a intentarlo cuando la conexión funcione.

Los archivos locales restantes y el estado local de KV pertenecen a esta VM desechable. Son independientes de los recursos de la nube que ya eliminó. Ahora puede finalizar el laboratorio.

Resumen

Creó un lector de configuración que acepta ajustes válidos antiguos y nuevos, utiliza valores predeterminados seguros para valores inexistentes o no válidos y mantiene su endpoint de estado independiente de los datos opcionales de KV. Probó una secuencia controlada de lecturas antiguas y, después, cambió una clave remota real y observó cómo convergía la respuesta implementada.

Aprendió que las etiquetas de versión describen los datos devueltos, mientras que la duración de la caché de lectura, la caducidad y la consistencia fuerte son conceptos diferentes. Por último, eliminó los recursos desechables y cerró la sesión. El desafío del curso combinará un binding correcto del espacio de nombres con una gestión segura de avisos.