fix: eager-load workspace.account in SocialAccountObserver to prevent lazy loading crash (#259)

* fix: eager-load workspace.account in SocialAccountObserver to prevent lazy loading crash

Closes #255

* fix: correct stale comment in VerifyUpcomingPostConnections about lazy-loading protection

Reflects that SocialAccountObserver::notifyOnboarding() now self-heals via loadMissing().
This commit is contained in:
Paulo Castellano 2026-08-09 10:39:30 -04:00 committed by GitHub
parent 9f4406e304
commit f019053860
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 3 deletions

View file

@ -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();
}

View file

@ -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()) {

View file

@ -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();