workspace->socialAccounts() ->with('workspace.owner') ->whereIn('status', [Status::Connected, Status::TokenExpired]) ->get(); if ($accounts->isEmpty()) { return; } $disconnectedAccounts = collect(); foreach ($accounts as $account) { if ($this->verifyAccount($verifier, $account)) { // If was TokenExpired but now verified OK, mark as connected again if ($account->status === Status::TokenExpired) { $account->markAsConnected(); } continue; } $disconnectedAccounts->push($account); } if ($disconnectedAccounts->isNotEmpty()) { $this->notifyOwner($disconnectedAccounts); } } private function verifyAccount(ConnectionVerifier $verifier, SocialAccount $account): bool { try { $verifier->verify($account); return true; } catch (TokenExpiredException $e) { Log::warning('Social account connection is invalid', [ 'account_id' => $account->id, 'platform' => $account->platform->value, 'error' => $e->getMessage(), ]); if ($account->status === Status::TokenExpired) { // Second failure — escalate to Disconnected $account->markAsDisconnected($e->getMessage()); } else { // First failure — mark as TokenExpired (softer state) $account->markAsTokenExpired($e->getMessage()); } return false; } catch (\Exception $e) { Log::error('Failed to verify social account connection', [ 'account_id' => $account->id, 'platform' => $account->platform->value, 'error' => $e->getMessage(), ]); // Unknown error — don't mark as disconnected, retry next time return true; } } /** * @param Collection $disconnectedAccounts */ private function notifyOwner(Collection $disconnectedAccounts): void { $owner = $this->workspace->owner; if (! $owner) { return; } $accountNames = $disconnectedAccounts ->map(fn ($account) => $account->platform->label().' (@'.($account->username ?? $account->display_name).')') ->implode(', '); SendNotification::dispatch( user: $owner, workspaceId: $this->workspace->id, type: Type::AccountDisconnected, channel: Channel::Both, title: $disconnectedAccounts->count().' '.($disconnectedAccounts->count() === 1 ? 'account' : 'accounts').' disconnected', body: $accountNames, data: ['workspace_id' => $this->workspace->id], mailable: new WorkspaceConnectionsDisconnected($this->workspace, $disconnectedAccounts), ); } }