1 points par GN⁺ 2023-09-29 | 1 commentaires | Partager sur WhatsApp
  • Deno Queues est une file distribuée serverless construite sur Deno KV, qui permet de déléguer des tâches longues en asynchrone ou de planifier une exécution à un moment futur
  • Le développeur n’a qu’à placer un message avec .enqueue() et le traiter avec .listenQueue(), sans avoir à configurer ni maintenir une infrastructure de file distincte
  • En local, le stockage repose sur SQLite ; sur Deno Deploy, sur FoundationDB, et Deploy lance à la demande un V8 isolate au moment du traitement des messages
  • Le mode de remise est at-least-once delivery, ce qui signifie qu’en cas de panne ou de nouvelle tentative, le même message peut être traité plusieurs fois
  • Il n’existe pas de tarification dédiée à la file, mais enqueue est compté comme une écriture KV, et la réception d’un message comme une écriture KV plus une requête Deno Deploy ; il faut donc tenir compte à la fois du traitement en double et de la structure des coûts

Ce que fait Deno Queues

  • Deno Queues est une fonctionnalité de file basée sur Deno KV, qui permet de déléguer une partie du traitement d’une application à des tâches asynchrones ou de planifier des travaux à exécuter plus tard
  • Deno vise à réduire les étapes répétitives de configuration et d’infrastructure dans le développement de logiciels cloud, afin de fournir les briques de base qui permettent aux développeurs de concevoir, améliorer et lancer plus rapidement
  • Deno KV est une option de persistance basée sur FoundationDB, actuellement en bêta ouverte
  • Queues fournit au-dessus de Deno KV une messagerie extensible et la gestion du traitement en arrière-plan

API de base et mode d’exécution

  • Deno Queues repose sur deux API principales
    • .enqueue() : ajoute un nouveau message à la file pour une remise immédiate ou à une date ultérieure
    • .listenQueue() : sert de gestionnaire pour recevoir et traiter les nouveaux messages de la file
  • Le flux de base consiste à ouvrir KV avec Deno.openKv(), envoyer un message Slack dans listenQueue, puis définir { delay: 60000 } dans enqueue pour un traitement 60 secondes plus tard
  • Le stockage diffère selon l’environnement d’exécution
    • En local : SQLite
    • Sur Deno Deploy : FoundationDB
  • Sur Deno Deploy, un V8 isolate est lancé à la demande lorsque le message devient traitable, puis le message est distribué
  • Le code applicatif se contente de recevoir les nouveaux messages dans le gestionnaire listenQueue, et Deno Deploy se charge du reste de l’exécution

Garantie de remise et nouvelles tentatives

  • Deno Queues garantit une at-least-once delivery
  • La plupart des messages envoyés via enqueue n’appellent le gestionnaire listenQueue qu’une seule fois, mais dans certaines situations d’échec, le même gestionnaire peut être invoqué plusieurs fois afin de garantir la remise
  • L’application doit donc pouvoir gérer en toute sécurité le traitement des messages en double
  • Si le gestionnaire listenQueue lève une exception, le runtime relance automatiquement l’appel
  • Les nouvelles tentatives continuent jusqu’au succès ou jusqu’à l’atteinte du nombre maximal de tentatives ; la valeur par défaut actuelle est de 5
  • Les messages ayant atteint le nombre maximal de tentatives sont supprimés

Utilisation avec les transactions atomiques KV

  • Deno Queues peut être combiné avec les KV atomic transactions
  • Si un message est ajouté à la file dans le cadre d’une transaction KV, il n’entre dans la file que si l’ensemble de la transaction réussit
  • Le scénario d’exemple consiste à vérifier puis mettre à jour les soldes de Bob et Liz, avant d’ajouter à la file des messages de notification pour chacun
    • check(bob, liz) vérifie l’état
    • Le solde de Bob est diminué et celui de Liz est augmenté
    • enqueue ajoute ensuite des messages de notification distincts pour Liz et Bob
    • commit() doit réussir pour que l’ensemble des modifications et l’ajout en file soient pris en compte
  • Il est également possible de mettre à jour l’état de Deno KV dans le gestionnaire listenQueue
  • Pour n’effectuer qu’une seule fois les mises à jour propres à chaque message, on peut construire un flux de prévention du traitement en double en stockant puis supprimant un nonce
    • Le nonce est stocké en même temps que le message lors de enqueue
    • Au moment du traitement, si le nonce n’existe pas, le gestionnaire retourne immédiatement
    • Si le traitement réussit, le nonce est supprimé et le compteur ainsi que l’état des soldes sont mis à jour ensemble

Cas d’usage adaptés à une file

  • Une file permet à un serveur de déléguer du traitement asynchrone et de planifier des tâches futures, ce qui est utile pour faire évoluer une application
  • Notifications e-mail planifiées

    • Lorsqu’une tâche déclenchée par l’utilisateur dure longtemps ou ne nécessite pas d’attendre une réponse de fin, la déléguer à une file permet de préserver la réactivité du serveur ou de l’application
    • Dans l’exemple, le message welcome_email est envoyé immédiatement via enqueue, tandis que survey_email est exécuté avec un délai via { delay: 259200000 }
  • Traitement fiable des webhooks

    • Mettre une requête webhook dans une file au lieu de la traiter immédiatement permet de séparer la réponse HTTP du traitement réel
    • En combinant Oak et Queues, une requête POST sur /webhook place le corps de la requête dans la file, puis renvoie HTTP 200
    • Le traitement réel du webhook est effectué de manière asynchrone dans listenQueue via processWebHook
  • Bots Slack et Discord

    • Queues peut aussi servir à construire des bots Discord ou Slack
    • L’exemple d’application de rappel Slack montre comment créer une application de rappel Slack simple avec Deno Queues
    • L’exemple de bot Discord utilise Deno Queues pour créer un giveaway auquel les utilisateurs peuvent participer en un clic
    • D’autres exemples d’usage des files sont disponibles sur docs.deno.com

Mode de tarification

  • Deno Queues n’a pas de ligne tarifaire dédiée
  • Les coûts sont calculés selon les opérations Deno KV et les requêtes Deno Deploy
    • Ajout d’un message dans la file : chaque opération enqueue correspond à 1 écriture KV
    • Réception d’un message : chaque message reçu entraîne 1 écriture KV et 1 requête facturable
  • La facturation repose uniquement sur les opérations réellement utilisées

Documentation et feuille de route

  • Documentation associée et références API
  • Pour créer des applications web et des serveurs extensibles, il faut pouvoir déléguer les tâches d’arrière-plan à une file, mais les approches existantes impliquent souvent de nombreuses étapes de configuration
  • Deno Queues est intégré au runtime et fonctionne sur l’infrastructure Deno Deploy, ce qui permet d’utiliser une file distribuée serverless avec seulement quelques lignes de code
  • Deno Queues se place aux côtés de Deno KV, des web standards APIs, de npm et de all-in-one modern tooling comme l’un des composants destinés à rendre le développement web plus simple et plus productif
  • Les retours et demandes de fonctionnalités peuvent être envoyés via Discord ou les issues deploy_feedback

1 commentaires

 
GN⁺ 2023-09-29
Avis sur Hacker News
  • Je viens de fouiller dans les entrailles de la version SQLite locale et de mettre mes notes au propre : https://til.simonwillison.net/deno/deno-kv#user-content-deno...
    La partie la plus intéressante est probablement le schéma utilisé par cette fonctionnalité :
    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);

    • Créer deux tables avec presque les mêmes champs et déplacer des lignes de l’une à l’autre, ça me semble généralement être une mauvaise pratique
      Les index ne sont-ils pas justement conçus pour ce genre d’usage ?
    • Ce qui est particulièrement intéressant du point de vue du « modèle économique open source », c’est que Deno intègre au cœur du framework une fonctionnalité que seule sa propre plateforme SaaS peut vraiment offrir correctement comme mise à niveau à l’échelle mondiale
      C’est assez nouveau, mais aussi un peu inquiétant. Bien sûr, il faut commercialiser, mais cela n’avait pas forcément besoin d’être complètement fermé ; ils auraient aussi pu utiliser une autre licence pour la couche d’extension, comme BSL ou PolyForm
  • La direction que Deno vise ici me paraît assez tournée vers l’avenir.
    J’utilise Go pour la première fois cette année, et une partie du langage ressemble beaucoup au C. Au-delà de ce qui le distingue du C — par exemple le fait que le garbage collector permette de renvoyer depuis une fonction des valeurs qui ressemblent à des pointeurs alloués sur la pile — des fonctionnalités intégrées comme map[string]string s’y intègrent naturellement. Si l’on créait un nouveau langage après 2023, l’absence de syntaxe intégrée pour manipuler des types map me semblerait presque inconcevable.
    Il paraît donc logique qu’un écosystème centré sur les serveurs web se dote de bibliothèques, voire peut-être un jour d’une syntaxe de langage, pour les primitives que nous utilisons souvent. Je ne me souviens pas du dernier projet de serveur web distribué qui n’avait même pas de stockage clé-valeur pour le cache, de mécanisme de verrouillage ou de file d’attente temporaire. Un système distribué sans stockage clé-valeur ressemble vaguement à un langage de programmation sans type map, et c’est vraiment une technologie de type couteau suisse.
    Le problème potentiel, c’est que Deno emprunte cette voie seul. Il est difficile de savoir si les nouvelles fonctionnalités que Deno ajoute aujourd’hui seront aussi proposées par les plateformes concurrentes, et même si l’API est publiée en open source, elle se trouve dans l’espace de noms Deno, donc je ne sais pas si cela fonctionnera tel quel quand on voudra, sur AWS, remplacer FoundationDB par Redis.
    C’est pour cela que j’ai le sentiment de vouloir éviter Deno. La syntaxe et les fonctionnalités exposées sont vraiment séduisantes, mais je crains de devoir pratiquer une grosse chirurgie du code après en être devenu dépendant, pour le rendre déployable sur plusieurs infrastructures cloud. Beaucoup de clients l’exigent. Par exemple, si un jour je veux vendre à Oracle ou Salesforce et qu’ils demandent une exécution on-premise, ce sera à moi de trouver comment adapter le stockage clé-valeur disponible chez eux aux fonctionnalités du package Deno.
    C’est à double tranchant. Deno pourrait réussir à imposer cette vision plus largement, mais pour l’instant je pense que je resterai prudent.

    • Dans ce cas, KV Connect, le protocole de connexion à distance, est également documenté : https://github.com/denoland/deno/tree/main/ext/kv#kv-connect
      J’ai un peu essayé kv-connect-kit, une implémentation de ce protocole en pur TypeScript, qui fournit une API cliente KV dans n’importe quel runtime JavaScript. Cela inclut aussi Cloudflare Workers, sans aucun espace de noms 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 / démo : https://keyspace.deno.dev/
      Le protocole semble fonctionner comme décrit, et écrire d’autres backends paraît aussi assez simple.
    • Je ne suis pas d’accord. Coupler un runtime de langage à une interface KV spécifique liée à un service d’hébergement particulier, c’est l’inverse d’une approche tournée vers l’avenir.
      Le secteur tech a fait pas mal de progrès pour s’éloigner des stacks captives de fournisseurs, et cela rappelle plutôt cette époque.
      Je ne vois pas de différence pratique entre le fait que Deno.KV soit inclus dans le runtime et le fait d’ajouter import KV en haut du fichier. Dans le second cas, on peut l’importer depuis Deno ou depuis n’importe où ailleurs.
      Et quelle est la probabilité que l’équipe Deno fournisse des bindings pour des langages autres que le sien ? Est-ce qu’on qualifierait de tourné vers l’avenir le fait que Google commence à intégrer nativement dans Go des primitives réservées à Google Cloud ?
    • J’aime Deno, mais pour les mêmes raisons je deviens prudent quant à son adoption. Pour que Deno gagne, il me semble qu’il doit aussi prendre entièrement en charge les concurrents dans l’hébergement.
      En même temps, son auto-hébergement doit être au niveau des leaders du secteur, voire meilleur. Une autre voie serait d’abandonner l’auto-hébergement et de proposer une solution multicloud avec une petite marge au-dessus d’adaptateurs vers des partenaires d’hébergement. Dans ce cas, Deno n’aurait plus besoin de concurrencer directement les fournisseurs d’hébergement.
    • Avec cela, Deno cherche simplement à concurrencer les autres SaaS JS/TS. Vercel/NextJS a aussi un service KV, Cloudflare en a un également, et dans d’autres cas il y a Firebase.
      À mon avis, il s’agit moins d’une démarche tournée vers l’avenir que d’une monétisation de Deno en tant que SaaS. C’est ce que tout le monde fait aujourd’hui dans l’écosystème JavaScript avec des produits “cloud” : adosser un framework et revendre AWS. C’est pour cela qu’il y a une grille tarifaire.
      Si le KV de Deno dépend de FoundationDB, il me semble aussi peu probable qu’ils créent activement des adaptateurs pour d’autres bases de données. Changer de technologie de base de données est toujours une grosse affaire, car chacune a ses usages et ses caractéristiques de performance.
    • GC allowing one to return what look like stack allocated pointers from functions me semble relever davantage de l’analyse d’échappement et de SSA que du garbage collection
  • L’argument selon lequel « pour utiliser une infrastructure de cloud public, il faut fouiller dans du code boilerplate et des configurations complexes, ce qui consomme beaucoup de temps et d’énergie côté développeurs » ne me convainc pas vraiment
    Au final, on construit une infrastructure qui doit être fiable. Passer 30 minutes à configurer une technologie éprouvée comme une file SQS ne me paraît pas pire que faire entièrement confiance à une file jouet créée par Deno « au-dessus de SQLite / FoundationDB ». Le coût de 30 minutes de configuration et une meilleure « expérience développeur » valent-ils vraiment de prendre ce risque ? Et puis, à quelle fréquence configure-t-on une file au départ ?

    • Je pense que ça dépend du profil de chacun
      En tant que programmeur amateur, je n’utilise pas beaucoup de grands fournisseurs comme AWS ou Google, parce que ça a l’air assez complexe. Une fois habitué, ce n’est peut-être pas si terrible
      Je veux aussi que chaque projet soit un dépôt GitHub indépendant. Idéalement, n’importe qui devrait pouvoir lancer l’application web facilement sur un domaine séparé, comme sa propre application web indépendante. Je n’ai pas envie d’être responsable des données des autres
      Ça ressemble dans une certaine mesure au cas d’usage de Sandstorm. Des instructions d’installation du type « essayez en local, puis créez un compte Deno Deploy pour l’utiliser réellement » me semblent assez raisonnables
    • Beaucoup de gens n’ont pas d’expérience avec AWS ou SQS, et même ceux qui en ont doivent quand même s’en occuper. Deno adopte une approche batteries incluses, pour que les développeurs puissent prendre quelque chose et l’utiliser tout de suite
      Si quelqu’un proposait une bibliothèque équivalente pour le cloud, il y aurait clairement des gens pour l’adopter. Dans le cas de Deno, ils semblent identifier les problèmes communs que rencontrent les développeurs de leur écosystème et les résoudre en empaquetant une solution correcte
    • Pour le dire de façon un peu radicale, je pense qu’il vaut mieux aujourd’hui éviter d’utiliser directement des files. C’est comparable au fait d’utiliser du HTTP/2 brut ou de gérer soi-même des threads
      Avec un moteur de workflow qui abstrait les files, on peut « juste écrire du code » sans gérer les tâches, la planification, l’état et les nouvelles tentatives
      https://www.inngest.com/blog/how-durable-workflow-engines-wo...
      Cela dit, je suis auteur d’un moteur de workflow, donc je suis biaisé
    • Avec ce raisonnement, tout ce qui sort de nouveau est par défaut un « projet jouet », et comme seul AWS est éprouvé, personne ne devrait lancer de nouveau produit
    • Comment sais-tu que c’est une file jouet ?
  • D’après mon expérience passée avec la « sémantique de livraison au moins une fois » et du « code utilisateur », les utilisateurs ne comprennent pas correctement la livraison au moins une fois
    Dès qu’un message est relivré, les plaintes des utilisateurs et les incidents affluent
    À mon avis, soit il faut réussir l’impossible et inventer une sémantique de livraison exactement une fois, soit il faut toujours relivrer 0,1 % de tous les messages pour empêcher les utilisateurs de compter sur une livraison unique

    • Les débuts de SQS étaient en pratique comme ça. Je ne sais pas si c’était intentionnel, mais ça m’a vite appris qu’il fallait respecter les relivraisons
    • Si les messages doivent être idempotents, je recommande vivement de créer des tests d’intégration qui le garantissent côté émetteur
  • J’utilise actuellement Deno Deploy, et pour des projets que je fais seul, les performances sont excellentes et c’est vraiment simple
    Ayant fait du développement AWS dans de grandes équipes, je suis content de voir ce mouvement qui s’éloigne de la complexité pour permettre de déployer facilement sans penser à la configuration. Le DNS était aussi très simple, et les certificats SSL automatiques sont vraiment appréciables. Je n’ai absolument rien à reprocher à l’objectif de ce produit, et j’attends aussi la roadmap avec intérêt

  • Sauf si j’ai raté quelque chose, il semble qu’il n’y ait qu’une seule file par instance de Deno.openKv()
    Dans la version locale, on pourrait créer plusieurs files en appelant Deno.openKv("db-2.db") avec un chemin de fichier SQLite différent à chaque fois, mais l’overhead semble important pour un besoin assez courant
    C’est peut-être le style architectural de Deno. Quand on construit une application complexe avec Deno, s’attend-on à une structure de type microservices, avec plusieurs scripts qui fonctionnent ensemble et disposent chacun de leur propre stockage KV et de leur propre file ?

    • Oui. Pour l’instant, il n’y a qu’une file unique
      Un des développeurs principaux l’a confirmé sur Discord : https://discord.com/channels/684898665143206084/115671428253...
      Pour citer : « Oui. Pour l’instant, une seule file est prise en charge. En revanche, il est possible de multiplexer plusieurs types de messages dans une seule file. »
  • Quel est le prix ?
    Je pensais que Deno était une sorte de remplaçant de Node.js ; qu’est-ce que j’ai raté ? Peut-on utiliser ça en local ou en auto-hébergement gratuitement ?

    • C’est le même fonctionnement que le reste de Deno KV. La version open source utilise SQLite, mais lorsque vous déployez sur l’offre cloud de Deno, elle utilise à la place FoundationDB, qui est propriétaire
      L’explication est que « Queues are built on Deno KV » : en local cela utilise SQLite, et sur Deno Deploy cela utilise FoundationDB pour une disponibilité et un débit maximaux
      J’ai écrit un peu plus sur ce modèle ici : https://til.simonwillison.net/deno/deno-kv
    • D’après l’article, pendant le développement cela utilise SQLite en local, et quand on déploie sur Deno, cela fait partie des fonctionnalités fournies par le cloud
  • Si des développeurs lisent ceci, avec l’excellente ergonomie actuelle de KV, j’ai l’impression que le contrôle d’accès risque de devenir douloureux plus tard
    Je me demande si la solution est simplement « implémentez-le vous-même dans l’espace utilisateur et ne faites pas de bugs », ou s’il y a quelque chose de prévu

    • Je me demande si vous parlez de contrôle d’accès au niveau utilisateur, par exemple des ACL pour utilisateurs authentifiés, ou d’autre chose. Si vous partagez une réflexion plus longue, je garderai cette préoccupation en tête
  • La prise en charge récente de Jupyter et cette fonctionnalité de files sont prometteuses. Ce sont vraiment de très belles choses
    Mais je ne pense pas écrire un serveur en Deno et le mettre en production sur mon propre serveur. Je n’aime pas le serverless
    Le modèle économique de Deno et de Bun est construit autour du serverless, c’est-à-dire Deno Deploy. Et Deno Deploy est encore un autre runtime
    C’est évident avec KV et les files. En local ou en auto-hébergement, on se retrouve avec une version qui fonctionne tant bien que mal au-dessus d’autres technologies
    Autrement dit, vous auto-hébergez une version de Deno différente de celle qu’utilisent la plupart des clients de Deno
    Combien de personnes utilisent Deno pour faire tourner des serveurs sur leur propre matériel ? Si ce nombre est faible, je préférerais autant utiliser Node

  • Deno est vraiment intéressant. C’est excellent d’avoir un modèle économique viable, une bonne ergonomie et pas de corvées de configuration inutiles

    • J’ai essayé d’avoir des attentes pour Deno, mais je ne suis pas convaincu. Je ne vois pas en quoi c’est différent de ce qui a déjà été fait d’innombrables fois par le passé.
      Deno lui-même, c’est essentiellement Node.js avec une compilation TypeScript automatique en plus. À l’origine, il aurait juste fallu un fichier de configuration supplémentaire. Quand le projet est sorti, il mettait fortement en avant le fait de s’affranchir de l’écosystème NPM désordonné, mais il a finalement dû faire marche arrière et ajouter la prise en charge de NPM, ce qui a aussi fait disparaître cet élément différenciant.
      Deno Deploy ressemble aux dizaines de services du type Lambda qui existent déjà. Le stockage KV, et maintenant les files d’attente, sont équivalents à Redis, LevelDB, RocksDB, Dynamo, SQS ou à quantité d’options similaires. Je n’ai encore vu aucune fonctionnalité qui distingue réellement Deno du reste.
      Si l’on préfère qu’une seule entreprise prenne en charge à la fois le runtime du langage, l’hébergement du calcul et le stockage des données, cela peut avoir un attrait. Mais personnellement, je préférerais l’éviter, surtout si cette entreprise n’a pas de références dans ce domaine.
    • Qu’est-ce qui te fait croire que Deno a un modèle économique viable ?