Introducción
Un banner de mantenimiento debe desaparecer cuando termina el periodo de publicación del aviso. Si permanece visible, los visitantes pueden pensar que una interrupción antigua sigue ocurriendo. Usted creará un Worker que lea un aviso de KV y decida si todavía debe mostrarse.
Hay dos plazos independientes. Un plazo de la aplicación indica a su código cuándo debe dejar de mostrar el mensaje. La expiración de KV indica al servicio de almacenamiento cuándo debe eliminar la entrada. Mantendrá deliberadamente en el almacenamiento un registro antiguo para demostrar que la aplicación puede ocultar contenido expirado aunque los datos sigan existiendo. Después observará cómo un segundo registro expira automáticamente en el KV de la nube.
Complete primero Serve Account Preferences. Esta VM independiente tiene Node.js 22.22.0 y Wrangler 4.131.1, instalado localmente para el proyecto, en /home/labex/project/temporary-notices. Utilice su propia cuenta de aprendizaje y los mismos permisos de lectura de la cuenta, escritura de Workers y escritura de KV. Creará un Worker y un espacio de nombres desechables, usará únicamente mensajes sintéticos y limpiará los recursos antes de cerrar la sesión. Este ejercicio breve no requiere comprar un dominio ni contratar una actualización de pago. Reserve unos cinco minutos para la observación temporizada, además del tiempo necesario para escribir y probar el controlador.
Conectar un espacio de nombres para avisos
En este paso, conectará un espacio de nombres nuevo para avisos temporales. Utilice un espacio de nombres independiente y un nombre único para el Worker, de modo que las pruebas de expiración no puedan eliminar datos de otra aplicación. El binding NOTICES conectará el controlador con este recurso.
Entre en el proyecto preparado:
cd /home/labex/project/temporary-notices
Genere una vez un nombre único. openssl rand -hex 6 imprime un sufijo aleatorio; $(...) lo inserta en el nombre. La variable de shell conservará ese nombre para los comandos siguientes en este terminal.
WORKER_NAME="labex-notices-$(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, mientras que 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 de 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 termine el inicio de sesión.
Revise los mismos permisos de escritura para Workers y KV que se introdujeron en Create a Feature Flag Store. Confirme su cuenta de aprendizaje antes de autorizar.
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 y sustituya 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. Como el delimitador no está entre comillas, el shell puede insertar $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 modificación del binding en lugar de cambiar el archivo automáticamente.
npx wrangler kv namespace create "$WORKER_NAME-notices" --update-config=false
La salida incluye el ID del espacio de nombres nuevo. Cópielo y sustituya YOUR_ACCOUNT_ID y YOUR_NAMESPACE_ID en esta configuración completa. El nombre del binding NOTICES 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": "NOTICES", "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.
Ocultar un aviso antiguo antes de eliminar sus datos
En este paso, separará el comportamiento de visualización de la limpieza del almacenamiento. Una marca de tiempo es un número que representa un momento. Aquí, displayUntil utiliza segundos Unix, contados desde el comienzo de 1970 en UTC. Date.now() devuelve milisegundos, por lo que el controlador divide el valor entre 1000 antes de compararlos. Usar la misma unidad evita un error habitual con los plazos.
Escriba el controlador con este documento here-document entre comillas:
cat > src/index.js <<'JS'
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.searchParams.get("key") ?? "notice:maintenance";
if (url.pathname !== "/notice" || !/^notice:[a-z]{1,20}$/.test(key)) {
return new Response("Not found", { status: 404 });
}
let entry;
try {
entry = await env.NOTICES.getWithMetadata(key, "text");
} catch {
return Response.json({ error: "Notice storage unavailable" }, { status: 503 });
}
if (entry.value === null) {
return Response.json({ visible: false, reason: "missing" });
}
let notice;
try {
notice = JSON.parse(entry.value);
} catch {
return Response.json({ visible: false, reason: "invalid" });
}
if (!notice || typeof notice.message !== "string" || !notice.message.trim() ||
!Number.isSafeInteger(notice.displayUntil) || notice.displayUntil <= 0) {
return Response.json({ visible: false, reason: "invalid" });
}
if (Math.floor(Date.now() / 1000) >= notice.displayUntil) {
return Response.json({ visible: false, reason: "expired" });
}
return Response.json({
visible: true, message: notice.message,
kind: entry.metadata?.kind === "maintenance" ? "maintenance" : "general"
});
}
};
JS
El parámetro de consulta key selecciona un aviso sintético; si no se especifica, el controlador utiliza notice:maintenance. La aplicación oculta los avisos ausentes, con formato incorrecto o expirados mediante una respuesta JSON explicativa. Un error de lectura de KV devuelve 503 en lugar de fingir que el aviso no existe. El campo de metadatos kind etiqueta el aviso; si faltan los metadatos o contienen un valor inesperado, se utiliza general.
La comparación del plazo utiliza >=: el aviso se oculta en el momento del plazo, no un segundo después. Esta comprobación se ejecuta en cada solicitud. Una página web que ya haya mostrado un banner también tendría que actualizarlo o quitarlo mediante su propio temporizador; una respuesta de Worker no puede cambiar por sí sola una página que ya se ha renderizado.
Guarde localmente un aviso de referencia deliberadamente antiguo. El plazo 1 corresponde a un instante conocido de 1970, por lo que este registro ya está expirado desde el punto de vista de la aplicación. Omitimos deliberadamente una expiración de KV para que el registro siga disponible para su inspección.
npx wrangler kv key put notice:reference '{"message":"Old maintenance notice","displayUntil":1}' --binding NOTICES --local --metadata '{"kind":"maintenance"}'
npx wrangler dev --local --ip 0.0.0.0 --port 8080 > local.log 2>&1 &
DEV_PID=$!
cat local.log
El servidor en segundo plano escribe la salida en local.log. Repita el comando de registro hasta que indique que está listo en el puerto 8080. Ahora solicite la referencia antigua:
curl -i 'http://127.0.0.1:8080/notice?key=notice:reference'
Espere HTTP 200 y {"visible":false,"reason":"expired"}. Las comillas impiden que el signo de interrogación de la URL se interprete como sintaxis de nombres de archivo del shell. Demuestre que la entrada todavía existe:
npx wrangler kv key get notice:reference --binding NOTICES --local --text
El JSON sigue presente. Su código, y no la eliminación automática, impidió que se mostrara el aviso antiguo. Una clave inexistente también debe procesarse de forma segura:
curl -i 'http://127.0.0.1:8080/notice?key=notice:missing'
Espere {"visible":false,"reason":"missing"}. Mantenga el servidor local en ejecución hasta la limpieza.
Publicar un aviso con dos plazos
En este paso, primero publicará el Worker y después iniciará un periodo breve de publicación en la nube. Preparar el endpoint antes de iniciar el contador le dará tiempo para inspeccionar el resultado activo.
Cree la misma referencia sin expiración en el espacio de nombres remoto:
npx wrangler kv key put notice:reference '{"message":"Old maintenance notice","displayUntil":1}' --binding NOTICES --remote --metadata '{"kind":"maintenance"}'
npx wrangler deploy
Confirme el nombre generado del Worker y el binding NOTICES. Después, guarde la URL pública real que aparece en la salida:
WORKER_URL="https://YOUR_WORKER.YOUR_SUBDOMAIN.workers.dev"
curl -i "$WORKER_URL/notice?key=notice:reference"
Espere que la referencia antigua aparezca oculta como expired. Si el nombre de host todavía no está disponible, espere y vuelva a intentarlo antes de comenzar la parte temporizada. Todavía no solicite la clave de mantenimiento predeterminada: las lecturas de claves de KV inexistentes también pueden almacenarse en caché.
Lea el resto de las instrucciones antes de ejecutar los comandos siguientes. date +%s devuelve la hora Unix actual de la VM; $((...)) realiza operaciones aritméticas en el shell. Dejaremos de mostrar el aviso después de tres minutos y pediremos a KV que lo elimine un minuto más tarde.
DISPLAY_UNTIL=$(($(date +%s) + 180))
KV_EXPIRES=$((DISPLAY_UNTIL + 60))
Escriba la carga útil real de la aplicación. El delimitador JSON sin comillas inserta el plazo numérico en el archivo:
cat > notice.json <<JSON
{"message":"Maintenance starts soon","displayUntil":$DISPLAY_UNTIL}
JSON
--path lee el valor desde ese archivo. --expiration establece una expiración absoluta de KV en segundos Unix; --metadata añade la categoría del aviso junto al valor.
npx wrangler kv key put notice:maintenance --path notice.json --binding NOTICES --remote --expiration "$KV_EXPIRES" --metadata '{"kind":"maintenance"}'
KV también admite un TTL relativo (tiempo de vida), expresado en segundos a partir de la escritura. Wrangler llama a esa opción --ttl; la API del binding la llama expirationTtl. Tanto la expiración relativa como la absoluta deben estar al menos 60 segundos en el futuro. Aquí utilizamos una expiración absoluta para que pueda comparar directamente los dos plazos. Consulte Opciones de expiración de KV.
npx wrangler kv key list --binding NOTICES --remote
Busque notice:maintenance, su expiration y sus metadatos kind. La referencia no tiene expiración de KV. Ahora lea el mensaje activo:
curl -i "$WORKER_URL/notice"
Espere HTTP 200 y {"visible":true,"message":"Maintenance starts soon","kind":"maintenance"}. Ejecute ahora la comprobación de este paso, antes de que se cierre el periodo de visualización. La comprobación analiza el valor real en la nube, los metadatos, la expiración de KV, el binding y la respuesta activa. Una marca de tiempo guardada por sí sola no demuestra que el aviso se haya almacenado.
Si pierde el periodo, repita las dos asignaciones de tiempo, vuelva a escribir notice.json y repita la escritura remota con plazos nuevos. No repita las escrituras rápidamente. Una lectura almacenada previamente en caché puede tardar en reflejar el reemplazo; tenga en cuenta ese retraso y repita la comprobación activa. Continúe solo después de que se complete correctamente.
Tras superar la comprobación activa, abra Storage & databases → Workers KV en el Dashboard de la misma cuenta de aprendizaje y seleccione el espacio de nombres del laboratorio. Abra KV Pairs y pulse View junto a notice:maintenance para ver el mensaje y displayUntil. Consulte la expiración de KV y los metadatos en la lista de claves de la CLI; esta vista muestra el valor almacenado. Solo lea los datos: el tiempo sigue transcurriendo. Si la clave ya expiró, continúe con el siguiente paso sin recrearla solo para verla. El nombre y la marca de tiempo de la captura son ejemplos que no debe copiar.

Observar el contenido oculto y la expiración automática
En este paso, observará los dos plazos sin eliminar manualmente la clave de mantenimiento. No modifique notice.json para poder comparar la carga útil original con el resultado.
Imprima los dos tiempos planificados y la hora actual:
printf 'displayUntil=%s
KV expiration=%s
now=%s
' "$DISPLAY_UNTIL" "$KV_EXPIRES" "$(date +%s)"
Espere hasta que la hora actual alcance displayUntil. Estos comandos calculan únicamente el retraso restante. Si el plazo ya pasó, la condición evita la espera. sleep recibe segundos; if impide pasarle un retraso negativo.
WAIT_SECONDS=$((DISPLAY_UNTIL - $(date +%s) + 1))
if [ "$WAIT_SECONDS" -gt 0 ]; then sleep "$WAIT_SECONDS"; fi
curl -i "$WORKER_URL/notice"
El mensaje ya no debe estar visible. Antes de que se produzca la expiración de KV, espere {"visible":false,"reason":"expired"}. Si vuelve después de que KV ya haya expirado la clave, reason puede ser missing; ambos resultados impiden la visualización. La referencia conservada sigue siendo una comprobación directa del comportamiento del plazo de la aplicación:
curl -i "$WORKER_URL/notice?key=notice:reference"
npx wrangler kv key get notice:reference --binding NOTICES --remote --text
El endpoint oculta la referencia como expired, mientras que la lectura de KV todavía devuelve su JSON antiguo. Esto demuestra por qué el plazo de la aplicación resulta útil incluso cuando los datos almacenados siguen disponibles.
Ahora espere hasta la hora de expiración de KV:
WAIT_SECONDS=$((KV_EXPIRES - $(date +%s) + 1))
if [ "$WAIT_SECONDS" -gt 0 ]; then sleep "$WAIT_SECONDS"; fi
npx wrangler kv key list --binding NOTICES --remote
curl -i "$WORKER_URL/notice"
La lista debería conservar únicamente notice:reference; el endpoint predeterminado debería devolver {"visible":false,"reason":"missing"}. No ejecute un comando de eliminación para la clave de mantenimiento: esta observación trata sobre la expiración automática. Si la entrada sigue apareciendo, repita las comprobaciones de solo lectura en intervalos de 15 segundos durante un máximo de dos minutos. Este es un periodo de observación del ejercicio, no una garantía sobre el momento exacto de la eliminación. Si el estado no converge, informe del resultado inconcluyente en lugar de afirmar que la operación tuvo éxito. Un error de autorización o de red no demuestra que la entrada haya desaparecido.
La expiración de KV y la caché de lectura son conceptos diferentes. La expiración se aplica aunque se haya solicitado una duración mayor para la caché de lectura. Sin embargo, los cambios en la configuración almacenada pueden propagarse con retraso, por lo que un nuevo plazo escrito después de una lectura anterior no constituye una garantía inmediata de programación global. Este laboratorio comprueba el plazo contenido en el registro que el controlador realmente lee.
Eliminar los recursos desechables de la nube
En este paso, eliminará ambos recursos mientras Wrangler todavía está autorizado. Un espacio de nombres puede sobrevivir a su Worker, por lo que eliminar solo 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-notices-... y el ID del espacio de nombres NOTICES. Elimine el Worker seleccionado mediante 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 al que hace referencia NOTICES. Esto también elimina el registro de referencia conservado:
npx wrangler kv namespace delete --binding NOTICES
Revise el espacio de nombres en cualquier solicitud de confirmación antes de aceptarla. 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 debería 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 expirada no demuestra que se haya producido la eliminación. 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 termina la autorización de Wrangler guardada en esta VM; no elimina recursos de la nube ni cierra la sesión de su navegador habitual en el Dashboard.
npx wrangler logout
npx wrangler whoami --json
Confirme que el resultado estructurado informa de "loggedIn": false. Este comando sin autenticación puede finalizar con un estado de salida distinto de cero, lo cual es normal en este punto. Si solo aparece un error de conexión y no un estado de autenticación explícito, 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 avisos que comprueba un plazo de visualización en cada solicitud, procesa de forma segura los datos ausentes o no válidos y lee una categoría de los metadatos de KV. Un registro antiguo conservado demostró que no es necesario eliminar primero el contenido para ocultarlo. Un segundo registro mostró la expiración de KV mediante una marca de tiempo absoluta y una comprobación independiente de eliminación automática.
Distinguió entre un plazo de visualización, una expiración de almacenamiento y el comportamiento de la caché de lectura. Después eliminó los recursos desechables y cerró la sesión. A continuación, importará y mantendrá un pequeño catálogo de redirecciones en KV.



