Source path: app/Jobs/PublishToPlatform.php
Extracted from supplied specification. Review before copying into application.

<?php
namespace App\Jobs;

use App\Events\PostFailed;
use App\Events\PostPublished;
use App\Models\PostTarget;
use App\Services\Publishers\PublisherFactory;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class PublishToPlatform implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public array $backoff = [60, 300, 900];
    public int $timeout = 300;

    public function __construct(public PostTarget $target) {}

    public function handle(PublisherFactory $factory): void
    {
        $this->target->increment('attempts');
        $this->target->update(['status' => 'publishing']);

        $result = $factory->for($this->target->socialAccount->platform)->publish($this->target);

        $this->target->update([
            'status' => 'published',
            'external_post_id' => $result['id'],
            'permalink' => $result['url'],
            'published_at' => now(),
            'error' => null,
        ]);

        $this->rollup();
        PostPublished::dispatch($this->target);
    }

    public function failed(\Throwable $e): void
    {
        $this->target->update(['status' => 'failed', 'error' => substr($e->getMessage(), 0, 2000)]);
        $this->rollup();
        PostFailed::dispatch($this->target);
    }

    private function rollup(): void
    {
        $post = $this->target->post()->with('targets')->first();
        $statuses = $post->targets->pluck('status');
        if ($statuses->contains(fn ($s) => in_array($s, ['pending', 'publishing']))) return;

        $post->update([
            'status' => $statuses->every(fn ($s) => $s === 'published') ? 'published'
                      : ($statuses->contains('published') ? 'partial' : 'failed'),
            'published_at' => now(),
        ]);
    }
}
