++ add reset program

This commit is contained in:
2026-07-29 14:26:36 +02:00
parent c6abef977d
commit 588910b893
14 changed files with 1524 additions and 183 deletions

View File

@@ -0,0 +1,179 @@
<?php
namespace App\Services;
use Illuminate\Support\Facades\Cache;
/**
* Stato di avanzamento delle operazioni lunghe di backup, ripristino e
* azzeramento.
*
* Le tre operazioni girano in coda e la pagina le segue interrogando questo
* stato: `total` e `processed` contano unita' di lavoro davvero completate
* (file scritti nell'archivio, file estratti, tabelle svuotate), non un
* temporizzatore. La barra si muove quando qualcosa e' finito sul disco.
*
* Stessa impostazione di TerritorioPdfImportState, con cui condivide anche il
* TTL: lo stato sopravvive un giorno, quindi ricaricare la pagina dopo un
* ripristino lungo mostra ancora l'esito.
*/
class BackupOperationState
{
public const TIPO_BACKUP = 'backup';
public const TIPO_RESTORE = 'restore';
public const TIPO_RESET = 'reset';
/** L'archivio e' pronto ma l'azzeramento aspetta che venga scaricato. */
public const FASE_ATTESA_DOWNLOAD = 'attesa-download';
protected int $ttlSeconds = 86400;
/** Coda dei log: solo le ultime righe, lo stato viaggia a ogni poll. */
private const MAX_LOG = 60;
public function initialize(string $id, string $tipo, string $fase, int $total = 0): array
{
$state = [
'id' => $id,
'tipo' => $tipo,
'status' => 'queued',
'fase' => $fase,
'total' => $total,
'processed' => 0,
'logs' => [],
'result' => [],
'error' => null,
'started_at' => null,
'finished_at' => null,
];
$this->put($id, $state);
return $state;
}
public function get(string $id): ?array
{
return Cache::get($this->key($id));
}
public function put(string $id, array $state): void
{
Cache::put($this->key($id), $state, $this->ttlSeconds);
}
public function forget(string $id): void
{
Cache::forget($this->key($id));
}
public function update(string $id, callable $callback): ?array
{
$state = $this->get($id);
if (! $state) {
return null;
}
$state = $callback($state) ?? $state;
$this->put($id, $state);
return $state;
}
public function log(string $id, string $message): void
{
$this->update($id, function (array $state) use ($message) {
$state['logs'][] = '[' . now()->format('H:i:s') . '] ' . $message;
$state['logs'] = array_slice($state['logs'], -self::MAX_LOG);
return $state;
});
}
/**
* Cambia fase e, insieme, il totale di riferimento: ogni fase ha una sua
* unita' di misura (file da comprimere, file da estrarre, passi di
* cancellazione) e la barra riparte da zero su quel totale.
*/
public function fase(string $id, string $fase, int $total = 0): void
{
$this->update($id, function (array $state) use ($fase, $total) {
$state['fase'] = $fase;
$state['total'] = $total;
$state['processed'] = 0;
return $state;
});
$this->log($id, $fase . ($total > 0 ? ' (' . $total . ')' : ''));
}
public function avanza(string $id, int $processed, ?int $total = null): void
{
$this->update($id, function (array $state) use ($processed, $total) {
$state['processed'] = $processed;
if ($total !== null) {
$state['total'] = $total;
}
return $state;
});
}
public function markRunning(string $id): void
{
$this->update($id, function (array $state) {
$state['status'] = 'running';
$state['started_at'] ??= now()->toDateTimeString();
return $state;
});
}
public function markCompleted(string $id, array $result = []): void
{
$this->update($id, function (array $state) use ($result) {
$state['status'] = 'completed';
$state['processed'] = max($state['processed'], $state['total']);
$state['result'] = $result + $state['result'];
$state['finished_at'] = now()->toDateTimeString();
return $state;
});
}
public function markFailed(string $id, string $error): void
{
$this->update($id, function (array $state) use ($error) {
$state['status'] = 'failed';
$state['error'] = $error;
$state['finished_at'] = now()->toDateTimeString();
return $state;
});
$this->log($id, 'ERRORE: ' . $error);
}
/**
* L'archivio e' pronto ma non si prosegue: l'azzeramento parte solo quando
* il download risulta consegnato per intero.
*/
public function markAttesaDownload(string $id, array $result): void
{
$this->update($id, function (array $state) use ($result) {
$state['status'] = 'running';
$state['fase'] = self::FASE_ATTESA_DOWNLOAD;
$state['processed'] = $state['total'];
$state['result'] = $result + $state['result'];
return $state;
});
}
protected function key(string $id): string
{
return 'backup-op:' . $id;
}
}