[{"data":1,"prerenderedAt":309},["ShallowReactive",2],{"\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fverrous-advisory":3,"section:\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fverrous-advisory":308},{"id":4,"title":5,"body":6,"description":294,"extension":295,"meta":296,"navigation":177,"path":304,"seo":305,"stem":306,"__hash__":307},"docs\u002F2.next\u002F3.dodock\u002F10.developpeurs\u002Fverrous-advisory.md","Verrous advisory",{"type":7,"value":8,"toc":289},"minimark",[9,13,17,25,41,48,91,98,152,155,159,162,244,251,255,285],[10,11,5],"h1",{"id":12},"verrous-advisory",[14,15,16],"p",{},"Un verrou advisory est un verrou nommé, tenu par la base de données. Il ne verrouille aucune ligne. Deux processus qui demandent le même nom s'attendent l'un l'autre. Utilisez-le pour qu'un seul processus à la fois exécute un traitement : un réapprovisionnement d'article, la génération d'un fichier, une synchronisation.",[18,19,21],"h2",{"id":20},"frappedbadvisory_lock",[22,23,24],"code",{},"frappe.db.advisory_lock",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","frappe.db.advisory_lock(key, *, timeout=10)\n","python","",[22,33,34],{"__ignoreMap":31},[35,36,39],"span",{"class":37,"line":38},"line",1,[35,40,29],{},[14,42,43,44,47],{},"C'est un gestionnaire de contexte. Il prend le verrou au début du bloc ",[22,45,46],{},"with"," et le libère à la sortie, même si le bloc lève une exception.",[49,50,51,64],"table",{},[52,53,54],"thead",{},[55,56,57,61],"tr",{},[58,59,60],"th",{},"Paramètre",[58,62,63],{},"Effet",[65,66,67,78],"tbody",{},[55,68,69,75],{},[70,71,72],"td",{},[22,73,74],{},"key",[70,76,77],{},"Nom du verrou (texte). Dodock le hache, donc une clé longue ne pose pas de problème",[55,79,80,85],{},[70,81,82],{},[22,83,84],{},"timeout",[70,86,87,88],{},"Attente maximale en secondes. Après ce délai, Dodock lève ",[22,89,90],{},"frappe.QueryTimeoutError",[14,92,93,94,97],{},"Le verrou est lié à la session de base de données, pas à la transaction. Il reste tenu après un ",[22,95,96],{},"frappe.db.commit()"," dans le bloc.",[49,99,100,110],{},[52,101,102],{},[55,103,104,107],{},[58,105,106],{},"Base",[58,108,109],{},"Mécanisme",[65,111,112,127,141],{},[55,113,114,117],{},[70,115,116],{},"PostgreSQL",[70,118,119,122,123,126],{},[22,120,121],{},"pg_try_advisory_lock",", puis ",[22,124,125],{},"pg_advisory_unlock"," à la sortie",[55,128,129,132],{},[70,130,131],{},"MariaDB",[70,133,134,122,137,140],{},[22,135,136],{},"GET_LOCK",[22,138,139],{},"RELEASE_LOCK"," à la sortie. Le nom est préfixé par la base du site, donc deux sites du même serveur ne partagent pas leurs verrous",[55,142,143,146],{},[70,144,145],{},"SQLite",[70,147,148,149],{},"Non disponible : lève ",[22,150,151],{},"NotImplementedError",[14,153,154],{},"Sur PostgreSQL, si une requête du bloc échoue, Dodock annule le travail du bloc jusqu'à un point de sauvegarde pris au début, puis libère le verrou.",[18,156,158],{"id":157},"exemple","Exemple",[14,160,161],{},"Exemple fictif : une méthode lance un réapprovisionnement. Deux clics simultanés ne doivent pas créer deux demandes de matériel.",[26,163,165],{"className":28,"code":164,"language":30,"meta":31,"style":31},"import frappe\n\n\n@frappe.whitelist()\ndef lancer_reapprovisionnement(item_code: str):\n    try:\n        with frappe.db.advisory_lock(f\"reappro:{item_code}\", timeout=5):\n            if frappe.db.exists(\"Material Request\", {\"docstatus\": 0, \"custom_article_reappro\": item_code}):\n                return False\n            creer_demande_materiel(item_code)  # fonction de votre application\n            return True\n    except frappe.QueryTimeoutError:\n        frappe.throw(\"Un réapprovisionnement est déjà en cours pour cet article.\")\n",[22,166,167,172,179,184,190,196,202,208,214,220,226,232,238],{"__ignoreMap":31},[35,168,169],{"class":37,"line":38},[35,170,171],{},"import frappe\n",[35,173,175],{"class":37,"line":174},2,[35,176,178],{"emptyLinePlaceholder":177},true,"\n",[35,180,182],{"class":37,"line":181},3,[35,183,178],{"emptyLinePlaceholder":177},[35,185,187],{"class":37,"line":186},4,[35,188,189],{},"@frappe.whitelist()\n",[35,191,193],{"class":37,"line":192},5,[35,194,195],{},"def lancer_reapprovisionnement(item_code: str):\n",[35,197,199],{"class":37,"line":198},6,[35,200,201],{},"    try:\n",[35,203,205],{"class":37,"line":204},7,[35,206,207],{},"        with frappe.db.advisory_lock(f\"reappro:{item_code}\", timeout=5):\n",[35,209,211],{"class":37,"line":210},8,[35,212,213],{},"            if frappe.db.exists(\"Material Request\", {\"docstatus\": 0, \"custom_article_reappro\": item_code}):\n",[35,215,217],{"class":37,"line":216},9,[35,218,219],{},"                return False\n",[35,221,223],{"class":37,"line":222},10,[35,224,225],{},"            creer_demande_materiel(item_code)  # fonction de votre application\n",[35,227,229],{"class":37,"line":228},11,[35,230,231],{},"            return True\n",[35,233,235],{"class":37,"line":234},12,[35,236,237],{},"    except frappe.QueryTimeoutError:\n",[35,239,241],{"class":37,"line":240},13,[35,242,243],{},"        frappe.throw(\"Un réapprovisionnement est déjà en cours pour cet article.\")\n",[14,245,246,247,250],{},"Le champ ",[22,248,249],{},"custom_article_reappro"," est un champ personnalisé de l'exemple.",[18,252,254],{"id":253},"conseils","Conseils",[256,257,258,266,269,272],"ul",{},[259,260,261,262,265],"li",{},"Choisissez une clé précise (",[22,263,264],{},"reappro:\u003Carticle>",") plutôt qu'une clé générale qui bloque tous les traitements.",[259,267,268],{},"Gardez le bloc court. Les autres processus attendent pendant toute sa durée.",[259,270,271],{},"Prenez toujours plusieurs verrous dans le même ordre, pour éviter un interblocage.",[259,273,274,275,278,279,284],{},"Sur PostgreSQL, pour un verrou libéré à la fin de la transaction, utilisez ",[22,276,277],{},"frappe.db.transaction_advisory_lock"," (voir ",[280,281,283],"a",{"href":282},"\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fverrous-transactionnels-postgresql","Verrous transactionnels dans PostgreSQL",").",[286,287,288],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":31,"searchDepth":38,"depth":174,"links":290},[291,292,293],{"id":20,"depth":174,"text":24},{"id":157,"depth":174,"text":158},{"id":253,"depth":174,"text":254},"Utiliser frappe.db.advisory_lock pour qu'un seul processus à la fois exécute un traitement sur une ressource logique.","md",{"icon":297,"reviewed":177,"last_verified":298,"sources":299},"i-mdi-lock-alert","2026-11-03",[300,301,302,303],"dodock@develop:frappe\u002Fdatabase\u002Fdatabase.py","dodock@develop:frappe\u002Fdatabase\u002Fmariadb\u002Fdatabase.py","dodock@develop:frappe\u002Fdatabase\u002Fpostgres\u002Fdatabase.py","dodock@develop:frappe\u002Ftests\u002Ftest_db.py","\u002Fnext\u002Fdodock\u002Fdeveloppeurs\u002Fverrous-advisory",{"title":5,"description":294},"2.next\u002F3.dodock\u002F10.developpeurs\u002Fverrous-advisory","RJDcwQ9cOFeR_vC8H4jb5K09QEcCn90OYMftvR4s2hA",{},1793871753948]