Piantine pubblicate anche dopo un ripristino; posto unico senza gare

- Lo stato "Pubblicata" non dipende più dall'id del territorio, che il
  ripristino ricrea: l'impronta usa il numero, e la piantina ricorda il
  percorso del PDF pubblicato (pdf_pubblicato, con migrazione che riconosce
  le piantine già pubblicate).
- BackupOperationState: corrente() in sola lettura e liberaCorrente() sotto
  lo stesso mutex di occupa(), così una lettura non cancella il puntatore
  di un'operazione appena avviata.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 15:33:07 +02:00
parent 426a95211d
commit e7148c7b32
8 changed files with 143 additions and 22 deletions

View File

@@ -112,10 +112,12 @@ class BackupOperationState
$stato = $this->get($id);
// Puntatore orfano (stato scaduto) o operazione gia' chiusa: il posto
// e' libero, e il puntatore va tolto di mezzo.
// e' libero. Il puntatore pero' qui non si tocca: corrente() la
// chiamano anche le pagine che si aggiornano, fuori dal mutex di
// occupa(), e cancellarlo poteva togliere quello che un'altra
// richiesta aveva appena scritto per un'operazione nuova. Lo
// sovrascrive initialize() al prossimo avvio.
if ($stato === null || in_array($stato['status'] ?? '', ['completed', 'failed'], true)) {
Cache::forget(self::CHIAVE_CORRENTE);
return null;
}
@@ -296,8 +298,17 @@ class BackupOperationState
*/
private function liberaCorrente(string $id): void
{
if (Cache::get(self::CHIAVE_CORRENTE) === $id) {
Cache::forget(self::CHIAVE_CORRENTE);
// Leggi-e-cancella sotto lo stesso mutex di occupa(): fra i due passi
// un'altra richiesta poteva prendere il posto, e il forget le toglieva
// il puntatore. Se il mutex non arriva si lascia stare: il puntatore a
// un'operazione chiusa vale già come posto libero (vedi corrente()).
try {
Cache::lock(self::CHIAVE_AVVIO, 10)->block(5, function () use ($id) {
if (Cache::get(self::CHIAVE_CORRENTE) === $id) {
Cache::forget(self::CHIAVE_CORRENTE);
}
});
} catch (LockTimeoutException) {
}
}