fix: handle complete empty snapshots and match dropdown trigger width

This commit is contained in:
Andras Bacsai 2026-08-16 18:26:40 +02:00
parent 9729e765b4
commit e28d8ca0ff
4 changed files with 23 additions and 21 deletions

View file

@ -188,7 +188,7 @@ public function handle()
Cache::forget($storageCacheKey);
}
if ($this->containers->isEmpty()) {
if ($this->containers->isEmpty() && ! $this->isCompleteSnapshot()) {
return;
}
@ -625,12 +625,6 @@ private function updateNotFoundApplicationStatus()
return;
}
// Only protection: Verify we received any container data at all
// If containers collection is completely empty, Sentinel might have failed
if ($this->containers->isEmpty()) {
return;
}
// Batch update: mark all not-found applications as exited (excluding already exited ones)
Application::whereIn('id', $notFoundApplicationIds)
->where('status', 'not like', 'exited%')
@ -644,12 +638,6 @@ private function updateNotFoundApplicationPreviewStatus()
return;
}
// Only protection: Verify we received any container data at all
// If containers collection is completely empty, Sentinel might have failed
if ($this->containers->isEmpty()) {
return;
}
// Collect IDs of previews that need to be marked as exited
$previewIdsToUpdate = collect();
foreach ($notFoundApplicationPreviewsIds as $previewKey) {
@ -738,12 +726,6 @@ private function updateNotFoundDatabaseStatus()
return;
}
// Only protection: Verify we received any container data at all
// If containers collection is completely empty, Sentinel might have failed
if ($this->containers->isEmpty()) {
return;
}
$notFoundDatabaseUuids->each(function ($databaseUuid) {
$database = $this->databasesByUuid->get($databaseUuid);
if ($database) {

View file

@ -35,7 +35,7 @@
const availableHeight = window.innerHeight - (edge * 2);
const triggerRect = trigger.getBoundingClientRect();
const desiredWidth = config.matchTriggerWidth
? Math.max(triggerRect.width, panel.offsetWidth)
? triggerRect.width
: panel.offsetWidth;
const panelWidth = Math.min(desiredWidth, availableWidth);
const panelHeight = Math.min(panel.scrollHeight, config.maxHeight ?? availableHeight);

View file

@ -77,7 +77,7 @@
expect($database->status)->toBe('running:healthy');
});
test('database is not marked exited when containers list is empty', function () {
test('database is not marked exited when an incomplete containers snapshot is empty', function () {
$team = Team::factory()->create();
$database = createPushUpdatePostgresql($team, [
'status' => 'running:healthy',
@ -88,6 +88,7 @@
// Empty containers = Sentinel might have failed, should NOT mark as exited
$data = [
'containers' => [],
'snapshot' => ['complete' => false],
];
$job = new PushServerUpdateJob($server, $data);
@ -99,6 +100,22 @@
expect($database->status)->toBe('running:healthy');
});
test('database is marked exited when a complete containers snapshot is empty', function () {
$team = Team::factory()->create();
$database = createPushUpdatePostgresql($team, [
'status' => 'running:healthy',
]);
$data = [
'containers' => [],
'snapshot' => ['complete' => true],
];
(new PushServerUpdateJob($database->destination->server, $data))->handle();
expect($database->refresh()->status)->toBe('exited:unhealthy');
});
function createPushUpdatePostgresql(Team $team, array $attributes = []): StandalonePostgresql
{
$lastOnlineAt = $attributes['last_online_at'] ?? null;

View file

@ -46,6 +46,9 @@
->toContain('window.floatingDropdown = function floatingDropdown')
->toContain('window.requestAnimationFrame')
->toContain('positionPanel(panel = null)')
->toContain('const desiredWidth = config.matchTriggerWidth')
->toContain('? triggerRect.width')
->not->toContain('? Math.max(triggerRect.width, panel.offsetWidth)')
->toContain('window.innerWidth < 768');
});