diff --git a/app/Jobs/PushServerUpdateJob.php b/app/Jobs/PushServerUpdateJob.php index fbf5cd154..9c4a2531a 100644 --- a/app/Jobs/PushServerUpdateJob.php +++ b/app/Jobs/PushServerUpdateJob.php @@ -188,7 +188,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced Cache::forget($storageCacheKey); } - if ($this->containers->isEmpty()) { + if ($this->containers->isEmpty() && ! $this->isCompleteSnapshot()) { return; } @@ -625,12 +625,6 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced 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 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced 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 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue, Silenced 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) { diff --git a/resources/views/components/floating-dropdown-script.blade.php b/resources/views/components/floating-dropdown-script.blade.php index f77bef831..81381c5cd 100644 --- a/resources/views/components/floating-dropdown-script.blade.php +++ b/resources/views/components/floating-dropdown-script.blade.php @@ -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); diff --git a/tests/Feature/PushServerUpdateJobLastOnlineTest.php b/tests/Feature/PushServerUpdateJobLastOnlineTest.php index a5f8f85ee..3746f2636 100644 --- a/tests/Feature/PushServerUpdateJobLastOnlineTest.php +++ b/tests/Feature/PushServerUpdateJobLastOnlineTest.php @@ -77,7 +77,7 @@ test('database status is updated when container status changes', function () { 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 @@ test('database is not marked exited when containers list is empty', function () // 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 @@ test('database is not marked exited when containers list is empty', function () 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; diff --git a/tests/Feature/StandardTableComponentsTest.php b/tests/Feature/StandardTableComponentsTest.php index ef5eef8c8..8e6a165e6 100644 --- a/tests/Feature/StandardTableComponentsTest.php +++ b/tests/Feature/StandardTableComponentsTest.php @@ -46,6 +46,9 @@ it('centralizes floating dropdown positioning in an Alpine data provider', funct ->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'); });