From f23e970587f07c990d94eed4b22065beb40cfe99 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 4 Nov 2025 17:24:46 +1100 Subject: [PATCH] HomeFeedPipeline defensive checks --- .../HomeFeedPipeline/FeedFollowPipeline.php | 13 +++++++++++ .../HomeFeedPipeline/FeedInsertPipeline.php | 15 ++++++++++++ .../FeedInsertRemotePipeline.php | 20 ++++++++++++++-- .../FeedRemoveDomainPipeline.php | 11 ++++++++- .../HomeFeedPipeline/FeedRemovePipeline.php | 22 +++++++++++++++--- .../FeedRemoveRemotePipeline.php | 20 ++++++++++++++-- .../HomeFeedPipeline/FeedUnfollowPipeline.php | 13 +++++++++++ .../FeedWarmCachePipeline.php | 8 +++++++ .../HashtagInsertFanoutPipeline.php | 15 ++++++++++++ .../HashtagRemoveFanoutPipeline.php | 15 ++++++++++++ .../HashtagUnfollowPipeline.php | 23 ++++++++++++++++++- 11 files changed, 166 insertions(+), 9 deletions(-) diff --git a/app/Jobs/HomeFeedPipeline/FeedFollowPipeline.php b/app/Jobs/HomeFeedPipeline/FeedFollowPipeline.php index e386329ca..9955b0e0f 100644 --- a/app/Jobs/HomeFeedPipeline/FeedFollowPipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedFollowPipeline.php @@ -14,6 +14,7 @@ use App\Services\AccountService; use App\Services\HomeTimelineService; use App\Services\SnowflakeService; use App\Status; +use Illuminate\Support\Facades\Log; class FeedFollowPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -69,6 +70,18 @@ class FeedFollowPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing $actorId = $this->actorId; $followingId = $this->followingId; + // Verify actor ID exists + if (!$actorId) { + Log::info("FeedFollowPipeline: Actor ID not provided, skipping job"); + return; + } + + // Verify following ID exists + if (!$followingId) { + Log::info("FeedFollowPipeline: Following ID not provided, skipping job"); + return; + } + $minId = SnowflakeService::byDate(now()->subWeeks(6)); $ids = Status::where('id', '>', $minId) diff --git a/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php b/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php index 4237a7b1a..eed84a488 100644 --- a/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedInsertPipeline.php @@ -15,6 +15,7 @@ use App\Models\UserDomainBlock; use App\Services\FollowerService; use App\Services\HomeTimelineService; use App\Services\StatusService; +use Illuminate\Support\Facades\Log; class FeedInsertPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -68,13 +69,27 @@ class FeedInsertPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing public function handle(): void { $sid = $this->sid; + $pid = $this->pid; + + // Verify required IDs are provided + if (!$sid) { + Log::info("FeedInsertPipeline: Missing status ID, skipping job"); + return; + } + if (!$pid) { + Log::info("FeedInsertPipeline: Missing profile ID, skipping job"); + return; + } + $status = StatusService::get($sid, false); if(!$status || !isset($status['account']) || !isset($status['account']['id'], $status['url'])) { + Log::info("FeedInsertPipeline: Status {$sid} not found or invalid, skipping job"); return; } if(!in_array($status['pf_type'], ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])) { + Log::info("FeedInsertPipeline: Status {$sid} type {$status['pf_type']} not supported, skipping job"); return; } diff --git a/app/Jobs/HomeFeedPipeline/FeedInsertRemotePipeline.php b/app/Jobs/HomeFeedPipeline/FeedInsertRemotePipeline.php index 6c4ce0c35..7dab26a01 100644 --- a/app/Jobs/HomeFeedPipeline/FeedInsertRemotePipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedInsertRemotePipeline.php @@ -15,6 +15,7 @@ use App\Models\UserDomainBlock; use App\Services\FollowerService; use App\Services\HomeTimelineService; use App\Services\StatusService; +use Illuminate\Support\Facades\Log; class FeedInsertRemotePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -68,9 +69,24 @@ class FeedInsertRemotePipeline implements ShouldQueue, ShouldBeUniqueUntilProces public function handle(): void { $sid = $this->sid; + $pid = $this->pid; + + // Verify status ID exists + if (!$sid) { + Log::info("FeedInsertRemotePipeline: Status ID not provided, skipping job"); + return; + } + + // Verify profile ID exists + if (!$pid) { + Log::info("FeedInsertRemotePipeline: Profile ID not provided, skipping job"); + return; + } + $status = StatusService::get($sid, false); if(!$status || !isset($status['account']) || !isset($status['account']['id'], $status['url'])) { + Log::info("FeedInsertRemotePipeline: Status {$sid} not found or invalid, skipping job"); return; } @@ -78,7 +94,7 @@ class FeedInsertRemotePipeline implements ShouldQueue, ShouldBeUniqueUntilProces return; } - $ids = FollowerService::localFollowerIds($this->pid); + $ids = FollowerService::localFollowerIds($pid); if(!$ids || !count($ids)) { return; @@ -105,7 +121,7 @@ class FeedInsertRemotePipeline implements ShouldQueue, ShouldBeUniqueUntilProces foreach($ids as $id) { if(!in_array($id, $skipIds)) { - HomeTimelineService::add($id, $this->sid); + HomeTimelineService::add($id, $sid); } } } diff --git a/app/Jobs/HomeFeedPipeline/FeedRemoveDomainPipeline.php b/app/Jobs/HomeFeedPipeline/FeedRemoveDomainPipeline.php index 018ea3794..57acdec67 100644 --- a/app/Jobs/HomeFeedPipeline/FeedRemoveDomainPipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedRemoveDomainPipeline.php @@ -13,6 +13,7 @@ use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; use App\Services\StatusService; use App\Services\HomeTimelineService; +use Illuminate\Support\Facades\Log; class FeedRemoveDomainPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -73,7 +74,15 @@ class FeedRemoveDomainPipeline implements ShouldQueue, ShouldBeUniqueUntilProces return; } - if(!$this->pid || !$this->domain) { + // Verify profile ID exists + if (!$this->pid) { + Log::info("FeedRemoveDomainPipeline: Profile ID not provided, skipping job"); + return; + } + + // Verify domain exists + if (!$this->domain) { + Log::info("FeedRemoveDomainPipeline: Domain not provided, skipping job"); return; } $domain = strtolower($this->domain); diff --git a/app/Jobs/HomeFeedPipeline/FeedRemovePipeline.php b/app/Jobs/HomeFeedPipeline/FeedRemovePipeline.php index 5c09d749a..b0ce11ce5 100644 --- a/app/Jobs/HomeFeedPipeline/FeedRemovePipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedRemovePipeline.php @@ -13,6 +13,7 @@ use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; use App\Services\FollowerService; use App\Services\StatusService; use App\Services\HomeTimelineService; +use Illuminate\Support\Facades\Log; class FeedRemovePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -65,12 +66,27 @@ class FeedRemovePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing */ public function handle(): void { - $ids = FollowerService::localFollowerIds($this->pid); + $sid = $this->sid; + $pid = $this->pid; - HomeTimelineService::rem($this->pid, $this->sid); + // Verify status ID exists + if (!$sid) { + Log::info("FeedRemovePipeline: Status ID not provided, skipping job"); + return; + } + + // Verify profile ID exists + if (!$pid) { + Log::info("FeedRemovePipeline: Profile ID not provided, skipping job"); + return; + } + + $ids = FollowerService::localFollowerIds($pid); + + HomeTimelineService::rem($pid, $sid); foreach($ids as $id) { - HomeTimelineService::rem($id, $this->sid); + HomeTimelineService::rem($id, $sid); } } } diff --git a/app/Jobs/HomeFeedPipeline/FeedRemoveRemotePipeline.php b/app/Jobs/HomeFeedPipeline/FeedRemoveRemotePipeline.php index d9ee716ba..2d57cf1e0 100644 --- a/app/Jobs/HomeFeedPipeline/FeedRemoveRemotePipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedRemoveRemotePipeline.php @@ -13,6 +13,7 @@ use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; use App\Services\FollowerService; use App\Services\StatusService; use App\Services\HomeTimelineService; +use Illuminate\Support\Facades\Log; class FeedRemoveRemotePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -65,10 +66,25 @@ class FeedRemoveRemotePipeline implements ShouldQueue, ShouldBeUniqueUntilProces */ public function handle(): void { - $ids = FollowerService::localFollowerIds($this->pid); + $sid = $this->sid; + $pid = $this->pid; + + // Verify status ID exists + if (!$sid) { + Log::info("FeedRemoveRemotePipeline: Status ID not provided, skipping job"); + return; + } + + // Verify profile ID exists + if (!$pid) { + Log::info("FeedRemoveRemotePipeline: Profile ID not provided, skipping job"); + return; + } + + $ids = FollowerService::localFollowerIds($pid); foreach($ids as $id) { - HomeTimelineService::rem($id, $this->sid); + HomeTimelineService::rem($id, $sid); } } } diff --git a/app/Jobs/HomeFeedPipeline/FeedUnfollowPipeline.php b/app/Jobs/HomeFeedPipeline/FeedUnfollowPipeline.php index 996e74c10..0d72d6a39 100644 --- a/app/Jobs/HomeFeedPipeline/FeedUnfollowPipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedUnfollowPipeline.php @@ -13,6 +13,7 @@ use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; use App\Services\AccountService; use App\Services\StatusService; use App\Services\HomeTimelineService; +use Illuminate\Support\Facades\Log; class FeedUnfollowPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -68,6 +69,18 @@ class FeedUnfollowPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing $actorId = $this->actorId; $followingId = $this->followingId; + // Verify actor ID exists + if (!$actorId) { + Log::info("FeedUnfollowPipeline: Actor ID not provided, skipping job"); + return; + } + + // Verify following ID exists + if (!$followingId) { + Log::info("FeedUnfollowPipeline: Following ID not provided, skipping job"); + return; + } + $ids = HomeTimelineService::get($actorId, 0, -1); foreach($ids as $id) { $status = StatusService::get($id, false); diff --git a/app/Jobs/HomeFeedPipeline/FeedWarmCachePipeline.php b/app/Jobs/HomeFeedPipeline/FeedWarmCachePipeline.php index 00cdbda65..68eefcdc2 100644 --- a/app/Jobs/HomeFeedPipeline/FeedWarmCachePipeline.php +++ b/app/Jobs/HomeFeedPipeline/FeedWarmCachePipeline.php @@ -11,6 +11,7 @@ use Illuminate\Queue\SerializesModels; use App\Services\HomeTimelineService; use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; +use Illuminate\Support\Facades\Log; class FeedWarmCachePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -62,6 +63,13 @@ class FeedWarmCachePipeline implements ShouldQueue, ShouldBeUniqueUntilProcessin public function handle(): void { $pid = $this->pid; + + // Verify profile ID exists + if (!$pid) { + Log::info("FeedWarmCachePipeline: Profile ID not provided, skipping job"); + return; + } + HomeTimelineService::warmCache($pid, true, 400, true); } } diff --git a/app/Jobs/HomeFeedPipeline/HashtagInsertFanoutPipeline.php b/app/Jobs/HomeFeedPipeline/HashtagInsertFanoutPipeline.php index eca598e49..9fdeb5d98 100644 --- a/app/Jobs/HomeFeedPipeline/HashtagInsertFanoutPipeline.php +++ b/app/Jobs/HomeFeedPipeline/HashtagInsertFanoutPipeline.php @@ -17,6 +17,7 @@ use App\Services\HomeTimelineService; use App\Services\StatusService; use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; +use Illuminate\Support\Facades\Log; class HashtagInsertFanoutPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -75,10 +76,24 @@ class HashtagInsertFanoutPipeline implements ShouldQueue, ShouldBeUniqueUntilPro public function handle(): void { $hashtag = $this->hashtag; + + // Verify hashtag exists + if (!$hashtag) { + Log::info("HashtagInsertFanoutPipeline: Hashtag no longer exists, skipping job"); + return; + } + + // Verify hashtag has status ID + if (!$hashtag->status_id) { + Log::info("HashtagInsertFanoutPipeline: Hashtag {$hashtag->id} has no status_id, skipping job"); + return; + } + $sid = $hashtag->status_id; $status = StatusService::get($sid, false); if(!$status || !isset($status['account']) || !isset($status['account']['id'], $status['url'])) { + Log::info("HashtagInsertFanoutPipeline: Status {$sid} not found or invalid, skipping job"); return; } diff --git a/app/Jobs/HomeFeedPipeline/HashtagRemoveFanoutPipeline.php b/app/Jobs/HomeFeedPipeline/HashtagRemoveFanoutPipeline.php index f1968e120..c03028a5a 100644 --- a/app/Jobs/HomeFeedPipeline/HashtagRemoveFanoutPipeline.php +++ b/app/Jobs/HomeFeedPipeline/HashtagRemoveFanoutPipeline.php @@ -15,6 +15,7 @@ use App\Services\HomeTimelineService; use App\Services\StatusService; use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing; +use Illuminate\Support\Facades\Log; class HashtagRemoveFanoutPipeline implements ShouldQueue, ShouldBeUniqueUntilProcessing { @@ -69,9 +70,23 @@ class HashtagRemoveFanoutPipeline implements ShouldQueue, ShouldBeUniqueUntilPro { $sid = $this->sid; $hid = $this->hid; + + // Verify status ID exists + if (!$sid) { + Log::info("HashtagRemoveFanoutPipeline: Status ID not provided, skipping job"); + return; + } + + // Verify hashtag ID exists + if (!$hid) { + Log::info("HashtagRemoveFanoutPipeline: Hashtag ID not provided, skipping job"); + return; + } + $status = StatusService::get($sid, false); if(!$status || !isset($status['account']) || !isset($status['account']['id'])) { + Log::info("HashtagRemoveFanoutPipeline: Status {$sid} not found or invalid, skipping job"); return; } diff --git a/app/Jobs/HomeFeedPipeline/HashtagUnfollowPipeline.php b/app/Jobs/HomeFeedPipeline/HashtagUnfollowPipeline.php index 232179ec3..10ffd1d7e 100644 --- a/app/Jobs/HomeFeedPipeline/HashtagUnfollowPipeline.php +++ b/app/Jobs/HomeFeedPipeline/HashtagUnfollowPipeline.php @@ -17,6 +17,7 @@ use App\StatusHashtag; use App\Services\HashtagFollowService; use App\Services\StatusService; use App\Services\HomeTimelineService; +use Illuminate\Support\Facades\Log; class HashtagUnfollowPipeline implements ShouldQueue { @@ -48,7 +49,27 @@ class HashtagUnfollowPipeline implements ShouldQueue { $hid = $this->hid; $pid = $this->pid; - $slug = strtolower($this->slug); + $slug = $this->slug; + + // Verify hashtag ID exists + if (!$hid) { + Log::info("HashtagUnfollowPipeline: Hashtag ID not provided, skipping job"); + return; + } + + // Verify profile ID exists + if (!$pid) { + Log::info("HashtagUnfollowPipeline: Profile ID not provided, skipping job"); + return; + } + + // Verify slug exists + if (!$slug) { + Log::info("HashtagUnfollowPipeline: Slug not provided, skipping job"); + return; + } + + $slug = strtolower($slug); $statusIds = HomeTimelineService::get($pid, 0, -1);