Colas de Deno
(deno.com)- Deno Queues es una cola distribuida serverless construida sobre Deno KV, que permite delegar trabajos largos de forma asíncrona o programar su ejecución para un momento futuro
- Los desarrolladores solo tienen que poner mensajes con
.enqueue()y procesarlos con.listenQueue(), sin necesidad de configurar ni mantener una infraestructura de colas aparte - En local usa SQLite, y en Deno Deploy usa FoundationDB; en Deploy, cuando llega el momento de procesar un mensaje, se levanta un V8 isolate on-demand para ejecutarlo
- El modo de entrega es at-least-once delivery, así que en escenarios de fallas o reintentos el mismo mensaje puede procesarse varias veces
- No hay un cobro separado por la cola, pero
enqueuecuenta como escritura en KV, y la recepción de mensajes se calcula como escritura en KV más una solicitud de Deno Deploy, por lo que conviene considerar tanto el procesamiento duplicado como la estructura de costos
Qué hace Deno Queues
- Deno Queues es una función de colas basada en Deno KV que permite pasar parte del procesamiento de una aplicación a trabajos asíncronos o programar tareas para ejecutarse más tarde
- Deno busca reducir la configuración repetitiva y la composición de infraestructura en el desarrollo de software en la nube, ofreciendo bloques base para que los desarrolladores puedan diseñar, mejorar y lanzar más rápido
- Deno KV es una opción de persistencia basada en FoundationDB y actualmente está en beta abierta
- Queues ofrece mensajería escalable y administración del procesamiento en segundo plano sobre Deno KV
API básica y forma de ejecución
- La API principal de Deno Queues tiene dos partes
.enqueue(): pone un mensaje nuevo en la cola para entregarlo de inmediato o en un momento futuro.listenQueue(): se usa como handler para recibir y procesar mensajes nuevos desde la cola
- El flujo básico consiste en abrir KV con
Deno.openKv(), enviar un mensaje de Slack enlistenQueuey especificar{ delay: 60000 }enenqueuepara que se procese 60 segundos después - El almacenamiento cambia según el entorno de ejecución
- En ejecución local usa SQLite
- En Deno Deploy usa FoundationDB
- En Deno Deploy, cuando un mensaje está listo para procesarse, se ejecuta un V8 isolate on-demand y se despacha el mensaje
- El código de la aplicación solo necesita recibir mensajes nuevos en el handler
listenQueue; Deno Deploy se encarga del resto de la ejecución
Garantía de entrega y reintentos
- Deno Queues garantiza at-least-once delivery
- La mayoría de los mensajes enviados con
enqueuellaman al handlerlistenQueueuna sola vez, pero en algunos escenarios de falla el mismo handler puede invocarse varias veces para garantizar la entrega - Por eso, la aplicación debe manejar de forma segura el procesamiento de mensajes duplicados
- Si el handler
listenQueuelanza una excepción, el runtime reintenta la llamada automáticamente - Los reintentos continúan hasta que tenga éxito o se alcance el número máximo de reintentos, cuyo valor predeterminado actual es 5
- Los mensajes que alcanzan el máximo de reintentos se eliminan
Uso junto con KV atomic transaction
- Deno Queues puede combinarse con KV atomic transactions
- Si un mensaje se pone en cola como parte de una transacción de KV, solo entra a la cola si toda la transacción se completa con éxito
- El flujo de ejemplo verifica y actualiza los saldos de Bob y Liz, y luego encola mensajes de notificación para ambos
- Se verifica el estado con
check(bob, liz) - Se reduce el saldo de Bob y se incrementa el de Liz
- Con
enqueuese agregan mensajes de notificación para Liz y Bob respectivamente - Solo si
commit()tiene éxito se aplican todos los cambios y el encolado
- Se verifica el estado con
- También se puede actualizar el estado de Deno KV dentro del handler
listenQueue - Si se quiere realizar una actualización por mensaje solo una vez, puede construirse un flujo de prevención de procesamiento duplicado guardando y eliminando un nonce
- Al encolar, se guarda también el nonce
- Al procesar, si no existe el nonce, se retorna de inmediato
- Si el procesamiento tiene éxito, se elimina el nonce y se actualizan junto con ello el contador y el estado del saldo
Casos de uso donde la cola encaja bien
- Las colas permiten que el servidor delegue procesamiento asíncrono y programe trabajos futuros, lo que resulta útil para escalar aplicaciones
-
Notificaciones por correo programadas
- Cuando una tarea iniciada por el usuario tarda mucho o no hace falta esperar una respuesta de finalización, se puede delegar el trabajo a la cola para mantener la capacidad de respuesta del servidor o de la app
- En el ejemplo, el mensaje
welcome_emailse encola de inmediato y el mensajesurvey_emailse ejecuta con retraso usando{ delay: 259200000 }
-
Procesamiento confiable de webhooks
- Si una solicitud de webhook no se procesa de inmediato y en cambio se pone en cola, puede separarse la respuesta HTTP del procesamiento real
- Usando Oak junto con Queues, al recibir una solicitud POST a
/webhook, el cuerpo de la solicitud se pone en la cola y se devuelve HTTP 200 - El procesamiento real del webhook se realiza de forma asíncrona en
listenQueueconprocessWebHook
-
Bots de Slack y Discord
- Queues también puede usarse para crear bots de Discord o Slack
- El ejemplo de Slack reminder app muestra cómo crear una app sencilla de recordatorios para Slack con Deno Queues
- El ejemplo de Discord bot usa Deno Queues para crear un giveaway en el que los usuarios pueden participar con un solo clic
- Se pueden ver más ejemplos de uso de colas en docs.deno.com
Cómo se cobra
- Deno Queues no tiene un concepto de cobro dedicado por separado
- El costo se calcula con base en las operaciones de Deno KV y las solicitudes de Deno Deploy
- Encolado de mensajes: cada operación
enqueueequivale a 1 escritura en KV - Recepción de mensajes: por cada mensaje recibido se genera 1 escritura en KV y 1 cargo por solicitud
- Encolado de mensajes: cada operación
- La estructura cobra solo por las operaciones realmente usadas
Documentación y roadmap
- Documentación relacionada y referencia de API
- Para crear apps web y servidores escalables, hace falta una arquitectura que delegue trabajos en segundo plano a una cola, pero los enfoques tradicionales suelen implicar muchos pasos de configuración
- Deno Queues viene integrado en el runtime y funciona sobre la infraestructura de Deno Deploy, permitiendo usar una cola distribuida serverless con apenas unas líneas de código
- Deno Queues se posiciona, junto con Deno KV, web standards APIs, npm y all-in-one modern tooling, como una pieza para hacer el desarrollo web más simple y productivo
- Los comentarios y solicitudes de funciones pueden enviarse a través de Discord o de los issues de deploy_feedback
1 comentarios
Opiniones de Hacker News
Acabo de profundizar en los detalles internos de la versión local de SQLite y recopilé algunas notas: https://til.simonwillison.net/deno/deno-kv#user-content-deno...
La parte más interesante probablemente sea el esquema que se usa para esta función:
CREATE TABLE queue ( ts integer not null, id text not null, data blob not null, backoff_schedule text not null, keys_if_undelivered blob not null, primary key (ts, id) );CREATE TABLE queue_running( deadline integer not null, id text not null, data blob not null, backoff_schedule text not null, keys_if_undelivered blob not null, primary key (deadline, id) );CREATE INDEX kv_expiration_ms_idx on kv (expiration_ms);¿No están diseñados los índices precisamente para ese tipo de cosas?
Es algo bastante novedoso, pero también un poco inquietante. Obviamente tienen que comercializarlo, pero no tenía por qué ser de una forma completamente cerrada; para la capa de expansión también podrían haber usado otra licencia como BSL o PolyForm.
Creo que la dirección a la que apunta Deno aquí es bastante orientada al futuro.
Este año empecé a usar Go por primera vez, y parte del lenguaje se parece mucho a C. Además de las diferencias con C, como que gracias al garbage collection se puedan devolver desde funciones valores que parecen punteros asignados en la pila, también incorpora de forma natural funcionalidades integradas como
map[string]string. Si se crea un lenguaje nuevo después de 2023, sentí que casi no tiene sentido que no tenga una sintaxis integrada para manejar tipos de mapa.Por eso parece lógico que un ecosistema centrado en servidores web cuente con librerías para las funcionalidades primitivas que usamos con frecuencia, y quizá algún día incluso con sintaxis del lenguaje. No recuerdo el último proyecto en el que un servidor web distribuido no tuviera siquiera un almacén clave-valor para caché, un mecanismo de bloqueo o una cola temporal. Un sistema distribuido sin almacén clave-valor se parece vagamente a un lenguaje de programación sin tipo mapa, y es realmente una tecnología tipo navaja suiza.
El problema potencial es que Deno está recorriendo este camino por su cuenta. Es difícil estar seguro de que las nuevas funciones que Deno está agregando hoy también vayan a estar disponibles en plataformas competidoras y, aunque publiquen la API como open source, al estar en el namespace
Deno, no sé si simplemente funcionará cuando quiera cambiar en AWS de FoundationDB a Redis.Por eso me da la sensación de que quiero evitar Deno. La sintaxis y las funciones expuestas son realmente atractivas, pero me preocupa tener que hacer una cirugía grande al código después de quedar atado, para poder desplegar en varias infraestructuras cloud. Muchos clientes piden eso. Por ejemplo, si algún día quiero venderle a Oracle o Salesforce y me exigen ejecutarlo on-premise, yo terminaría cargando con el problema de cómo adaptar el almacén clave-valor que puedan usar ellos a las funciones del paquete
Deno.Es un arma de doble filo. Deno podría lograr empujar esta visión a un público más amplio, pero por ahora creo que lo voy a mirar con cautela.
Probé un poco
kv-connect-kit, que implementa este protocolo en TypeScript puro, y ofrece una API de cliente KV en cualquier runtime de JavaScript. Eso incluye Cloudflare Workers, donde no hay ningún namespace de Deno.GitHub: https://github.com/skymethod/kv-connect-kit / npm: https://www.npmjs.com/package/kv-connect-kit / deno/x: https://deno.land/x/kv_connect_kit / demo: https://keyspace.deno.dev/
El protocolo parece funcionar tal como se describe, y escribir otros backends también se ve bastante sencillo.
La industria tecnológica ha avanzado bastante para alejarse de stacks con lock-in de proveedor, y esto más bien recuerda a esa época.
No sé cuál es la diferencia práctica entre que
Deno.KVvenga incluido como parte del runtime y agregarimport KVal inicio del archivo. Lo segundo se puede importar desde donde uno quiera, sea Deno o cualquier otro lugar.¿Y qué tan probable es que el equipo de Deno ofrezca bindings para lenguajes que no sean el suyo? ¿También llamaríamos orientado al futuro que Google empezara a meter de forma nativa en Go funcionalidades primitivas exclusivas de Google Cloud?
Al mismo tiempo, su propio hosting tiene que estar al nivel de los líderes de la industria o ser mejor. Otro camino sería abandonar el hosting propio y ofrecer una solución multicloud con un margen pequeño sobre adaptadores de partners de hosting. Así Deno no tendría que competir directamente como proveedor de hosting.
Más que algo orientado al futuro, me parece una forma de monetizar Deno como SaaS. Es lo que hoy hace cualquiera en el mundo JavaScript con productos de “cloud”: pegarle un framework y revender AWS. Por eso tiene una lista de precios.
Si el KV de Deno depende de FoundationDB, tampoco parece muy probable que creen activamente adaptadores para otras bases de datos. Cambiar de tecnología de base de datos siempre es un asunto grande, porque cada una tiene usos y características de rendimiento distintos.
GC allowing one to return what look like stack allocated pointers from functionsno me parece tanto gracias al garbage collection, sino más bien gracias al análisis de escape y a SSANo me convence mucho el argumento de que “para aprovechar la infraestructura de nube pública hay que meterse con código repetitivo y configuraciones complejas, lo que consume mucho tiempo y energía de los desarrolladores”.
Al final, estamos construyendo infraestructura que debe ser estable. No me parece peor dedicar 30 minutos a configurar una tecnología probada como colas SQS que confiar plenamente en una cola de juguete que Deno creó “sobre SQLite / FoundationDB”. ¿De verdad el costo de 30 minutos de configuración y una mejor “experiencia de desarrollador” valen tanto como para asumir ese riesgo? Para empezar, ¿con qué frecuencia se configura una cola?
Como programador aficionado, no suelo usar grandes proveedores como AWS o Google porque parecen bastante complejos. Si ya estás familiarizado, quizá no sea tan malo.
También quiero mantener cada proyecto como un repositorio independiente en GitHub. Idealmente, cualquiera debería poder levantar fácilmente la app web en un dominio separado como si fuera su propia app web independiente. Es porque no quiero hacerme responsable de los datos de otras personas.
Esto se parece en cierta medida a un caso de uso de Sandstorm. Una guía de instalación del tipo “pruébalo localmente y, si quieres usarlo de verdad, crea una cuenta de Deno Deploy” suena bastante razonable.
Si alguien ofreciera una biblioteca equivalente para la nube, sin duda habría gente que la adoptaría. En el caso de Deno, parece que están identificando problemas comunes que enfrentan los desarrolladores de su ecosistema y empaquetando soluciones razonables para resolverlos.
Si usas un motor de workflows que abstraiga las colas, puedes “simplemente escribir código” sin gestionar tareas, programaciones, estado ni reintentos.
https://www.inngest.com/blog/how-durable-workflow-engines-wo...
Eso sí, soy autor de un motor de workflows, así que tengo sesgo.
Por mi experiencia previa tratando con “semántica de entrega al menos una vez” y “código de usuario”, los usuarios no entienden bien la entrega al menos una vez.
En cuanto reenvías un mensaje, empiezan a llover quejas de usuarios e incidentes.
Creo que habría que lograr lo casi imposible e inventar una semántica de entrega exactamente una vez, o bien reenviar siempre el 0.1% de todos los mensajes para que los usuarios no puedan depender de que se entreguen una sola vez.
Actualmente uso Deno Deploy y, para un proyecto que hago solo, el rendimiento es excelente y es realmente simple.
Habiendo desarrollado con AWS en equipos grandes, me alegra esta tendencia de alejarse de la complejidad para poder desplegar fácilmente sin pensar en la configuración. El DNS también fue muy sencillo y los certificados SSL automáticos son realmente buenos. No tengo ninguna queja sobre hacia dónde apunta este producto, y me entusiasma su roadmap.
Si no se me pasó algo, parece que hay una sola cola por cada instancia de
Deno.openKv().En la versión local, probablemente puedas crear varias colas llamando a
Deno.openKv("db-2.db")con una ruta distinta de archivo SQLite cada vez, pero parece mucho overhead para un requisito bastante común.Tal vez sea el estilo arquitectónico de Deno. Al crear apps complejas con Deno, ¿esperan una estructura tipo microservicios donde varios scripts funcionan juntos y cada uno tiene su propio almacén KV y su propia cola?
Uno de los desarrolladores principales lo confirmó en Discord: https://discord.com/channels/684898665143206084/115671428253...
Cito: “Correcto. Actualmente solo admitimos una única cola. Sin embargo, puedes multiplexar múltiples tipos de mensajes en una única cola”.
¿Cómo es el precio?
Pensaba que Deno era una especie de reemplazo de Node.js; ¿me estoy perdiendo algo? ¿Se puede usar esto localmente o en self-hosting sin costo?
Como “Queues are built on Deno KV”, la explicación es que localmente usa SQLite, y en Deno Deploy usa FoundationDB para máxima disponibilidad y throughput.
Escribí un poco más sobre este patrón aquí: https://til.simonwillison.net/deno/deno-kv
Si por casualidad los desarrolladores están leyendo esto, creo que con la excelente usabilidad actual de KV, el lado del control de acceso podría causar dolor más adelante.
Me pregunto si la solución es simplemente “impleméntenlo ustedes mismos en el espacio de usuario y no introduzcan bugs”, o si hay algo planeado.
El soporte reciente para Jupyter y esta función de colas me entusiasman. Son cosas realmente geniales.
Pero no creo que vaya a escribir servidores con Deno y ponerlos en producción en mi propio servidor. No me gusta serverless.
Los modelos de negocio de Deno y Bun están construidos alrededor de serverless, es decir, Deno Deploy. Y Deno Deploy es otro runtime.
Eso queda claro con KV y las colas. En local o en self-hosting, tienes una versión que apenas funciona montada sobre otras tecnologías.
Es decir, terminarías haciendo self-hosting de una versión de Deno distinta de la que usa la mayoría de los clientes de Deno.
¿Cuánta gente usará Deno para correr servidores en su propio hardware? Si ese número es bajo, mejor usaría Node.
Deno es realmente interesante. Es excelente que tenga un modelo de negocio viable, buena usabilidad y nada de tareas inútiles de configuración.
Deno en sí es, en esencia, Node.js con compilación automática de TypeScript. En condiciones normales, solo habría hecho falta un archivo de configuración más. Cuando salió el proyecto, se destacó mucho que permitía alejarse del ecosistema desordenado de NPM, pero al final tuvieron que dar marcha atrás y agregar soporte para NPM, y esa diferenciación también desapareció.
Deno Deploy es igual a las decenas de servicios tipo Lambda que ya existen. El almacenamiento KV y ahora las colas están al nivel de Redis, LevelDB, RocksDB, Dynamo, SQS o muchísimas opciones similares. Todavía no he visto ni una sola función que realmente diferencie a Deno del resto.
Si prefieres que una sola empresa se encargue del runtime del lenguaje, el hosting de cómputo y el almacenamiento de datos, puede resultar atractivo. Pero personalmente preferiría evitarlo, sobre todo si esa empresa no tiene trayectoria en ese campo.