id, 0) ->delay(now()->addSeconds(self::BACKOFF[0])) ->onQueue('low'); return true; } public static function pendingKey(string $id): string { return 'pf:ap:reply-resolve:pending:'.hash('sha256', $id); } public function handle(): void { $id = Helpers::pluckval($this->object['id'] ?? null); if (! is_string($id) || ! Helpers::validateUrl($id)) { return; } $profile = Profile::find($this->profileId); // Author deleted, suspended or somehow local: nothing to store. if (! $profile || $profile->domain === null || $profile->status !== null) { $this->finish($id); return; } // Stored in the meantime by another path (Announce, Like, search). if (Helpers::findExistingStatus($id)) { $this->finish($id); return; } $resolution = Helpers::resolveReplyParent($this->object, $profile); if ($resolution['state'] === Helpers::REPLY_PARENT_UNRESOLVED) { $this->retryOrDrop($id); return; } if (Helpers::replyParentAllowsStore($resolution)) { Helpers::storeStatus($id, $profile, $this->object); } $this->finish($id); } private function retryOrDrop(string $id): void { $next = $this->attempt + 1; if (! isset(self::BACKOFF[$next])) { Log::info('RemoteReplyResolvePipeline: parent never resolved, dropping reply', [ 'id' => $id, 'inReplyTo' => $this->object['inReplyTo'] ?? null, 'attempts' => $next, ]); $this->finish($id); return; } self::dispatch($this->object, $this->profileId, $next) ->delay(now()->addSeconds(self::BACKOFF[$next])) ->onQueue('low'); } private function finish(string $id): void { Cache::forget(self::pendingKey($id)); } }