Dokos supporte désormais les verrous transactionnels advisory pour PostgreSQL, permettant de sécuriser des sections critiques de validation sans verrouiller des lignes de données. Cette fonctionnalité est particulièrement utile pour les développeurs qui doivent implémenter des logiques de validation complexes tout en maintenant la cohérence des données.
La fonction frappe.db.transaction_advisory_lock(key) utilise le verrou pg_advisory_xact_lock de PostgreSQL, qui présente les caractéristiques suivantes :
Pour utiliser un verrou transactionnel advisory dans votre code :
# Acquérir un verrou transactionnel
if frappe.db.db_type == "postgres":
frappe.db.transaction_advisory_lock("ma_cle_unique")
# Effectuer des opérations critiques
try:
# Validation des données
# ...
frappe.db.commit() # Le verrou est libéré ici
except Exception:
frappe.db.rollback() # Le verrou est libéré ici
Lors de la valorisation des stocks en batch, il est crucial d'éviter les conflits entre plusieurs mouvements simultanés sur le même article. Plutôt que de verrouiller toutes les lignes d'historique des mouvements de stock (SLE), vous pouvez utiliser un verrou transactionnel advisory :
if frappe.db.db_type == "postgres":
frappe.db.transaction_advisory_lock(f"stock_valuation_{item_code}")
# Calculer la valorisation du stock
# ...
GET_LOCK (qui est de portée session et non transactionnelle).Vous pouvez vérifier les verrous actifs dans PostgreSQL avec la requête suivante :
SELECT locktype, objid, transactionid, mode, granted
FROM pg_locks
WHERE locktype = 'advisory';
Voici un exemple complet d'utilisation dans un contexte de valorisation de stock :
def calculate_batch_valuation(item_code, warehouse):
if frappe.db.db_type == "postgres":
frappe.db.transaction_advisory_lock(f"valuation_{item_code}_{warehouse}")
try:
# Récupérer les mouvements de stock
sle = frappe.get_all(
"Stock Ledger Entry",
filters={
"item_code": item_code,
"warehouse": warehouse
},
fields=["*"],
order_by="posting_date"
)
# Calculer la valorisation
valuation = 0
for entry in sle:
valuation += entry.stock_value_difference
# Mettre à jour l'article
frappe.db.set_value(
"Item",
item_code,
"standard_rate",
valuation / frappe.db.get_value("Item", item_code, "actual_qty")
)
frappe.db.commit()
except Exception as e:
frappe.db.rollback()
frappe.throw(f"Erreur lors de la valorisation : {str(e)}")
| Base de données | Support | Alternative |
|---|---|---|
| PostgreSQL | ✅ Oui | - |
| MariaDB | ❌ Non | GET_LOCK |
Cette fonctionnalité est particulièrement utile pour les applications personnalisées qui nécessitent une synchronisation fine des opérations sans impact sur les performances globales du système.