Retour au Blog
Plateforme

Web Locks API : coordonner le travail partagé en sécurité

Coordonnez onglets, fenêtres et workers avec Web Locks API sans confondre les verrous du navigateur avec ceux d’un serveur distribué.

BotBrowser Team

Documentation

Vous voulez la documentation structurée pour Plateforme ?

Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.

Quand plusieurs onglets ou workers modifient la même ressource du navigateur, « vérifier puis écrire » ne suffit pas : deux contextes peuvent réussir ensemble. Web Locks API met en file les demandes nommées afin qu’un seul contexte d’une origine possède la section critique. Elle ne coordonne ni les serveurs ni les origines différentes et ne répare pas seule un état abandonné. BotBrowser peut répéter un profil autorisé, mais n’accorde pas de verrou et ne remplace pas la correction de l’application ou du serveur.

Flux abstrait où plusieurs contextes du navigateur convergent vers une section critique sérialisée puis reprennent leur travail.

TL;DR

  • Placez le verrou autour de l’opération partagée la plus courte et libérez-le au retour du callback.
  • Utilisez ifAvailable ou une échéance applicative quand l’attente est inutile ; un refus n’est pas une acquisition.
  • Un worker, un onglet ou une fenêtre peut disparaître. Rendez l’opération idempotente et gardez la récupération hors du callback.
  • Web Locks coordonne les contextes navigateur de même origine, pas les pages cross-origin ni les processus serveur.
  • BotBrowser peut répéter un parcours de profil autorisé, mais la page reste responsable du verrou, du stockage et de l’annulation.

Sommaire

Le modèle de verrou

navigator.locks.request(name, options, callback) met en file un verrou nommé. Le mode exclusif est le défaut ; le mode partagé autorise plusieurs lecteurs tout en excluant un écrivain exclusif. Le callback ne s’exécute qu’après attribution et le verrou reste détenu jusqu’à son retour ou la résolution de sa promise. Un autre contexte de même origine attend dans la file au lieu d’interroger un indicateur de stockage.

Cette file n’est pas un mutex global du backend : elle ne traverse ni origines, profils, appareils ni instances serveur. Gardez la section protégée courte : lire, valider une modification, écrire, retourner. Les appels réseau et attentes d’interface vont généralement hors verrou ; une décision durable exige une transaction ou un bail côté serveur.

Un petit fixture

Ce fixture incrémente un compteur local et indique si le verrou a été obtenu. Avec ifAvailable, lock vaut null lorsqu’un autre contexte le possède.

async function incrementCounter(storage, report) {
  if (!navigator.locks) return report('unsupported');
  return navigator.locks.request('counter-write', { ifAvailable: true }, async lock => {
    if (!lock) return report('busy');
    const current = Number(storage.getItem('counter') || 0);
    storage.setItem('counter', String(current + 1));
    report('committed');
  });
}

Deux contextes concurrents n’entrent pas ensemble ; un contexte occupé signale busy et un navigateur sans API unsupported. C’est un exemple local : localStorage n’est pas transactionnel. Pour une donnée importante, utilisez un stockage adapté et revérifiez les conflits au serveur.

Sécurité du worker et reprise

Un worker peut demander le même nom qu’une fenêtre. S’il est arrêté pendant l’attente ou le callback, le navigateur libère le verrou, mais une écriture partielle ou un effet externe restent à gérer. Utilisez une clé d’idempotence et distinguez « non démarré », « validé » et « inconnu après interruption ». N’attendez pas le réseau sous verrou.

Évitez les files sans limite pour les actions utilisateur. ifAvailable convient au rafraîchissement facultatif ; le travail obligatoire a besoin d’une échéance et d’un contrôle d’annulation avant chaque étape irréversible. Retournez toujours du callback et fermez les ports du worker à l’arrêt.

BotBrowser permet de répéter des parcours de profils autorisés pour une revue de compatibilité. Il n’accorde pas de Web Lock, ne force pas un autre onglet à libérer son verrou et ne remplace pas les transactions serveur.

Preuves et matrice

Utilisez deux fenêtres de même origine et un worker, un nom unique, un compteur et un arrêt forcé. Notez version, profil, mode headed/headless, stockage, résultat visible et valeur finale ; ne conservez pas de données de compte ni de captures brutes.

ObservationInterprétation prudenteAction
Un committed par demande acceptéeLa section s’est sérialisée dans ce testGarder court et retester après mise à jour
busy avec ifAvailableLe verrou était occupéConserver l’état et décider d’une reprise visible
unsupportedL’API manque dans ce contextePrévoir un repli ou une transaction serveur
Worker arrêté avant le rapportRésultat potentiellement inconnuRéconcilier par clé idempotente avant reprise
Compteur faux malgré la sérieStockage ou validation non atomiqueDéplacer l’invariant dans un stockage transactionnel

Le fixture montre un comportement observable, pas une coordination distribuée. Vérifiez aussi le message d’état, le formulaire conservé et une reprise sans doublon.

Définir la ressource et le callback

Le nom doit désigner la ressource protégée, pas l’écran. Séparez les invariants et évitez un verrou global qui retarde le travail indépendant. Le callback doit lire, valider, écrire puis retourner ; le verrou est libéré quand sa promise se termine. Réseau, attente utilisateur et animation restent hors verrou.

Une exception libère le verrou mais ne prouve pas qu’un effet externe est terminé. AbortController.abort() ne révoque pas un callback déjà commencé : il avertit seulement le code qui observe le signal. Vérifiez l’annulation avant chaque étape irréversible et rendez la reprise idempotente.

Disparition du propriétaire et échéance

Un onglet, une fenêtre ou un worker peut disparaître. Le navigateur libère alors le verrou, mais l’application doit enregistrer une intention avec une clé d’idempotence et réconcilier son outbox : distinguer non démarré, validé et inconnu avant de réessayer. Avec ifAvailable, busy conserve l’état ; le travail obligatoire a une échéance, jamais une boucle serrée.

Support et nouvelle vérification

Séparez API présente, opération terminée et résultat visible. Une version de navigateur ne remplace pas le fixture. Testez API absente, rejet, échec de stockage et arrêt du worker ; gardez un statut accessible et une reprise utilisable au clavier. Réexaminez noms, repli et rétention après un changement de navigateur, stockage ou mode hors ligne.

Conclusion

Web Locks convient à une coordination brève entre contextes de même origine. Gardez les écritures atomiques, rendez l’interruption récupérable et placez les invariants durables dans un stockage qui dépasse le navigateur. Exécutez ensuite le fixture deux fenêtres/worker avec votre vrai repli et vérifiez l’enregistrement final.

FAQ

Le verrou protège-t-il une ligne serveur ?

Non. Le serveur doit encore gérer autorisation, conflits et transaction ou idempotence.

Puis-je forcer sa libération après un délai ?

Non. Le navigateur le libère à la fin du callback ou du contexte propriétaire. Concevez l’annulation et évitez le travail lent sous verrou.

ifAvailable est-il un échec ?

C’est le choix de ne pas attendre. null signifie que l’opération n’a pas eu lieu ; gardez l’état et choisissez une reprise explicite.

BotBrowser rend-il la planification déterministe ?

Non. Il rend un parcours de profil compatible répétable, pas la planification, le stockage ou la reprise de l’application.

Sources et lectures

Sources

#Web Locks API#Workers#Coordination Navigateur#Concurrence

Faites passer BotBrowser de la recherche à la production

Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.