diff --git a/app/Jobs/VerifyUpcomingPostConnections.php b/app/Jobs/VerifyUpcomingPostConnections.php index b2186f7b3..311a75031 100644 --- a/app/Jobs/VerifyUpcomingPostConnections.php +++ b/app/Jobs/VerifyUpcomingPostConnections.php @@ -335,9 +335,9 @@ private function atRiskPostPlatforms(): Collection // socialAccount.workspace is eager-loaded even though this job // never reads it directly — SocialAccountObserver::notifyOnboarding() // (fired by the ->update() calls below via markAsTokenExpired()) - // accesses $account->workspace, and lazy loading is disabled - // app-wide. Dropping this eager load throws LazyLoadingViolationException - // the moment a second account in the same run gets updated (see #255). + // reads $account->workspace. The observer self-heals with + // loadMissing() (see #255), but without this eager load every + // account in the batch triggers its own extra query there. ->with(['socialAccount.workspace', 'post']) ->get(); } diff --git a/app/Observers/SocialAccountObserver.php b/app/Observers/SocialAccountObserver.php index 413bafdff..1a8f95fc2 100644 --- a/app/Observers/SocialAccountObserver.php +++ b/app/Observers/SocialAccountObserver.php @@ -76,6 +76,8 @@ private function syncUsageAndOnboarding(SocialAccount $socialAccount): void */ private function notifyOnboarding(SocialAccount $socialAccount): void { + $socialAccount->loadMissing('workspace.account'); + $account = $socialAccount->workspace?->account; if (! $account?->isOnboardingOpen()) { diff --git a/tests/Feature/Observers/SocialAccountObserverTest.php b/tests/Feature/Observers/SocialAccountObserverTest.php index d85f84264..a2fad5485 100644 --- a/tests/Feature/Observers/SocialAccountObserverTest.php +++ b/tests/Feature/Observers/SocialAccountObserverTest.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use App\Enums\SocialAccount\Status; use App\Jobs\PostHog\SyncAccountUsage; use App\Models\Account; use App\Models\SocialAccount; @@ -64,3 +65,18 @@ Bus::assertNotDispatched(SyncAccountUsage::class); }); + +test('updating status on multiple batch-hydrated social accounts does not throw a lazy loading violation', function () { + $accounts = SocialAccount::factory()->count(2)->create([ + 'workspace_id' => $this->workspace->id, + 'status' => Status::Connected, + ]); + + $batch = SocialAccount::query() + ->whereIn('id', $accounts->pluck('id')) + ->get(); + + foreach ($batch as $socialAccount) { + $socialAccount->update(['status' => Status::Disconnected]); + } +})->throwsNoExceptions();