fix(backups): sync Backup Now with live database status
Subscribe BackupEdit to database status broadcasts and refresh the database status so the Backup Now control updates without a full reload.
This commit is contained in:
parent
ddbed9f8a6
commit
8cfa41a7d9
2 changed files with 89 additions and 0 deletions
|
|
@ -9,6 +9,7 @@
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Livewire\Attributes\Locked;
|
use Livewire\Attributes\Locked;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
@ -84,17 +85,49 @@ class BackupEdit extends Component
|
||||||
#[Validate(['required', 'int', 'min:60', 'max:36000'])]
|
#[Validate(['required', 'int', 'min:60', 'max:36000'])]
|
||||||
public int|string $timeout = 3600;
|
public int|string $timeout = 3600;
|
||||||
|
|
||||||
|
public function getListeners(): array
|
||||||
|
{
|
||||||
|
// Keep "Backup Now" in sync when the database starts/stops without a full page refresh.
|
||||||
|
$listeners = ['databaseUpdated' => 'refreshStatus'];
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
if (! $user) {
|
||||||
|
return $listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
$listeners["echo-private:user.{$user->id},DatabaseStatusChanged"] = 'refreshStatus';
|
||||||
|
|
||||||
|
$team = $user->currentTeam();
|
||||||
|
if ($team) {
|
||||||
|
$listeners["echo-private:team.{$team->id},ServiceChecked"] = 'refreshStatus';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $listeners;
|
||||||
|
}
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->authorize('view', $this->backup->database);
|
$this->authorize('view', $this->backup->database);
|
||||||
$this->parameters = get_route_parameters();
|
$this->parameters = get_route_parameters();
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
|
$this->refreshStatus();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function refreshStatus(): void
|
||||||
|
{
|
||||||
|
$database = $this->backup->database;
|
||||||
|
if (! $database) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$database->refresh();
|
||||||
|
$this->status = $database->status;
|
||||||
|
}
|
||||||
|
|
||||||
public function syncData(bool $toModel = false)
|
public function syncData(bool $toModel = false)
|
||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
|
|
|
||||||
|
|
@ -430,3 +430,59 @@ function createS3StorageForBackupEditValidationTest(Team|int $team, string $name
|
||||||
expect($backup->save_s3)->toBeFalsy();
|
expect($backup->save_s3)->toBeFalsy();
|
||||||
expect($backup->s3_storage_id)->toBe($secondS3->id);
|
expect($backup->s3_storage_id)->toBe($secondS3->id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('subscribes to database status broadcasts so Backup Now can refresh without a full page reload', function () {
|
||||||
|
$component = app(BackupEdit::class);
|
||||||
|
$method = new ReflectionMethod($component, 'getListeners');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
$listeners = (array) $method->invoke($component);
|
||||||
|
|
||||||
|
expect($listeners)
|
||||||
|
->toHaveKey("echo-private:user.{$this->user->id},DatabaseStatusChanged")
|
||||||
|
->toHaveKey("echo-private:team.{$this->team->id},ServiceChecked")
|
||||||
|
->toHaveKey('databaseUpdated');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows Backup Now after refresh when the database becomes running', function () {
|
||||||
|
$backup = createBackupForEditValidationTest($this->team, [
|
||||||
|
'enabled' => true,
|
||||||
|
]);
|
||||||
|
$database = $backup->database;
|
||||||
|
$database->update(['status' => 'exited:unhealthy']);
|
||||||
|
|
||||||
|
$component = Livewire::test(BackupEdit::class, [
|
||||||
|
'backup' => $backup->fresh(),
|
||||||
|
'availableS3Storages' => $this->team->s3s,
|
||||||
|
'status' => 'exited:unhealthy',
|
||||||
|
])
|
||||||
|
->assertDontSee('Backup Now')
|
||||||
|
->assertSet('status', 'exited:unhealthy');
|
||||||
|
|
||||||
|
$database->update(['status' => 'running:healthy']);
|
||||||
|
|
||||||
|
$component->call('refreshStatus')
|
||||||
|
->assertSet('status', 'running:healthy')
|
||||||
|
->assertSee('Backup Now');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides Backup Now after refresh when the database stops', function () {
|
||||||
|
$backup = createBackupForEditValidationTest($this->team, [
|
||||||
|
'enabled' => true,
|
||||||
|
]);
|
||||||
|
$database = $backup->database;
|
||||||
|
$database->update(['status' => 'running:healthy']);
|
||||||
|
|
||||||
|
$component = Livewire::test(BackupEdit::class, [
|
||||||
|
'backup' => $backup->fresh(),
|
||||||
|
'availableS3Storages' => $this->team->s3s,
|
||||||
|
'status' => 'running:healthy',
|
||||||
|
])
|
||||||
|
->assertSee('Backup Now')
|
||||||
|
->assertSet('status', 'running:healthy');
|
||||||
|
|
||||||
|
$database->update(['status' => 'exited:unhealthy']);
|
||||||
|
|
||||||
|
$component->call('refreshStatus')
|
||||||
|
->assertSet('status', 'exited:unhealthy')
|
||||||
|
->assertDontSee('Backup Now');
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue