Pour l'instant il n'y a aucune protection au niveau de l'API pour empêcher de faire deux patchs en même temps ou de faire un undo pendant qu'on traite un patch. C'était un choix assumé au niveau de conception parce que:
l'API devait être mono utilisateur (une branche par utilisateur, en tous cas dans les premières versions de l'API)
on devait s'assurer, côté client, qu'on attendait bien une réponse avant de lancer une nouvelle requête de modification
En pratique, même si on n'a qu'un seul utilisateur par branche, il n'est pas si simple de garantir de façon certaine qu'il n'y a pas plusieurs modifications lancées en même temps. Surtout si cela ne concerne pas uniquement des modifications, mais aussi la simple lecture du cache. Des conflits sur une branche pourraient se produire en cas de lecture (des WMTS/GetTile générés par un rafraîchissement ou un déplacement) pendant l'application d'un patch, d'un undo ou redo. La probabilité devant encore plus forte si:
l'API est très chargée: le temps d'application d'un patch, d'un undo/redo devenant plus long
on utilise un grand nombre d'instances (avec PM2 et/ou un HAProxy): le traitement des requêtes devient encore plus asynchrone qu'avec une seule instance de nodeJs (qui a tendance à traiter les requête plus ou moins dans l'ordre)
Si on veut utiliser un drapeau ou un verrou pour protéger l'API, la seule façon propre de partager l'information entre toutes les instances, c'est d'utiliser la BD Postgres. On pourrait mettre un verrou sur la table des branches (ou sur la ligne qui correspond à la branche qui nous intéresse), mais il faut faire très attention à l'impact sur les performances. En particulier sur les requêtes WMTS/GetTiles qui sont très nombreuses et concernent souvent la même branche (iTowns ou QGis lançant beaucoup de requêtes en parallèle pour rafraichir la vue).
D'après la doc Postgres (https://www.postgresql.org/docs/current/explicit-locking.html) lorsqu'on veut un verrou pour garantir un comportement côté applicatif (et non pour éviter une modification concurrente de la BD), le mécanisme des "Advisory locks" est plus efficace. Il existe une version au niveau de la transaction qui est automatiquement libérée à la fin de la transaction (ce qui élimine les risques de verrou mortel en cas d'erreur en cours de transaction).
En pratique, on pourrait imaginer un:
pg_advisory_xact_lock_shared(id_branch) en début de transaction pour une lecture simple (WMTS/GetTile, requête graph ou récupération de la liste de tous les patchs d'une branche): on peut en faire autant que nécessaire en parallèle, elles ne se bloquent pas mutuellement
pg_advisory_xact_lock(id_branch) en début de transaction pour une modification (patch, patch/undo, patch/redo, patches/clear): cette requête attendra qu'il n'y ai pas de lock_shared en cours sur cet id, et une fois que le lock est activé les nouvelles demandes de lock ou lock_shared resteront en attente tant que la transaction n'est pas terminée
En faisant une seule demande de verrou par transaction on est certain de ne jamais avoir des demandes croisées qui s'attendent mutuellement.
Pour l'instant il n'y a aucune protection au niveau de l'API pour empêcher de faire deux patchs en même temps ou de faire un undo pendant qu'on traite un patch. C'était un choix assumé au niveau de conception parce que:
En pratique, même si on n'a qu'un seul utilisateur par branche, il n'est pas si simple de garantir de façon certaine qu'il n'y a pas plusieurs modifications lancées en même temps. Surtout si cela ne concerne pas uniquement des modifications, mais aussi la simple lecture du cache. Des conflits sur une branche pourraient se produire en cas de lecture (des WMTS/GetTile générés par un rafraîchissement ou un déplacement) pendant l'application d'un patch, d'un undo ou redo. La probabilité devant encore plus forte si:
Si on veut utiliser un drapeau ou un verrou pour protéger l'API, la seule façon propre de partager l'information entre toutes les instances, c'est d'utiliser la BD Postgres. On pourrait mettre un verrou sur la table des branches (ou sur la ligne qui correspond à la branche qui nous intéresse), mais il faut faire très attention à l'impact sur les performances. En particulier sur les requêtes WMTS/GetTiles qui sont très nombreuses et concernent souvent la même branche (iTowns ou QGis lançant beaucoup de requêtes en parallèle pour rafraichir la vue).
D'après la doc Postgres (https://www.postgresql.org/docs/current/explicit-locking.html) lorsqu'on veut un verrou pour garantir un comportement côté applicatif (et non pour éviter une modification concurrente de la BD), le mécanisme des "Advisory locks" est plus efficace. Il existe une version au niveau de la transaction qui est automatiquement libérée à la fin de la transaction (ce qui élimine les risques de verrou mortel en cas d'erreur en cours de transaction).
En pratique, on pourrait imaginer un:
En faisant une seule demande de verrou par transaction on est certain de ne jamais avoir des demandes croisées qui s'attendent mutuellement.