fedi-feed-router/app/Jobs/PublishNextArticleJob.php

109 lines
3.6 KiB
PHP
Raw Normal View History

2025-08-12 20:16:44 +02:00
<?php
namespace App\Jobs;
use App\Enums\LogLevelEnum;
use App\Enums\NotificationSeverityEnum;
use App\Enums\NotificationTypeEnum;
use App\Events\ActionPerformed;
2025-08-12 20:16:44 +02:00
use App\Exceptions\PublishException;
use App\Models\Article;
use App\Models\ArticlePublication;
use App\Models\Setting;
2025-08-12 20:16:44 +02:00
use App\Services\Article\ArticleFetcher;
use App\Services\Notification\NotificationService;
2025-08-12 20:16:44 +02:00
use App\Services\Publishing\ArticlePublishingService;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class PublishNextArticleJob implements ShouldBeUnique, ShouldQueue
2025-08-12 20:16:44 +02:00
{
use Queueable;
/**
* The number of seconds after which the job's unique lock will be released.
*/
public int $uniqueFor = 300;
public function __construct()
{
$this->onQueue('publishing');
}
/**
* Execute the job.
*
2025-08-12 20:16:44 +02:00
* @throws PublishException
*/
public function handle(ArticleFetcher $articleFetcher, ArticlePublishingService $publishingService, NotificationService $notificationService): void
2025-08-12 20:16:44 +02:00
{
$interval = Setting::getArticlePublishingInterval();
if ($interval > 0) {
$lastPublishedAt = ArticlePublication::max('published_at');
if ($lastPublishedAt && now()->diffInMinutes($lastPublishedAt, absolute: true) < $interval) {
return;
}
}
2025-08-12 20:16:44 +02:00
// Get the oldest approved article that hasn't been published yet
2025-08-12 20:55:57 +02:00
$article = Article::where('approval_status', 'approved')
2025-08-12 20:16:44 +02:00
->whereDoesntHave('articlePublication')
2025-08-12 21:07:46 +02:00
->oldest('created_at')
2025-08-12 20:16:44 +02:00
->first();
if (! $article) {
return;
}
ActionPerformed::dispatch('Publishing next article from scheduled job', LogLevelEnum::INFO, [
2025-08-12 20:16:44 +02:00
'article_id' => $article->id,
'title' => $article->title,
'url' => $article->url,
'created_at' => $article->created_at,
2025-08-12 20:16:44 +02:00
]);
try {
$extractedData = $articleFetcher->fetchArticleData($article);
$publications = $publishingService->publishToRoutedChannels($article, $extractedData);
if ($publications->isNotEmpty()) {
ActionPerformed::dispatch('Successfully published article', LogLevelEnum::INFO, [
'article_id' => $article->id,
'title' => $article->title,
]);
} else {
ActionPerformed::dispatch('No publications created for article', LogLevelEnum::WARNING, [
'article_id' => $article->id,
'title' => $article->title,
]);
$notificationService->send(
NotificationTypeEnum::PUBLISH_FAILED,
NotificationSeverityEnum::WARNING,
"Publish failed: {$article->title}",
'No publications were created for this article. Check channel routing configuration.',
$article,
);
}
2025-08-12 20:16:44 +02:00
} catch (PublishException $e) {
ActionPerformed::dispatch('Failed to publish article', LogLevelEnum::ERROR, [
2025-08-12 20:16:44 +02:00
'article_id' => $article->id,
'error' => $e->getMessage(),
2025-08-12 20:16:44 +02:00
]);
$notificationService->send(
NotificationTypeEnum::PUBLISH_FAILED,
NotificationSeverityEnum::ERROR,
"Publish failed: {$article->title}",
$e->getMessage(),
$article,
);
2025-08-12 20:16:44 +02:00
throw $e;
}
}
}