Proje dosyaları eklendi
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Enums\SerpCheckStatus;
|
||||
use App\Models\SerpCheck;
|
||||
use App\Serp\Contracts\AsyncSerpProvider;
|
||||
use App\Serp\Exceptions\SerpProviderException;
|
||||
use App\Serp\Exceptions\UnexpectedProviderResponseException;
|
||||
use App\Serp\Operations\OperationAuditLogger;
|
||||
use App\Serp\SerpProviderRegistry;
|
||||
use App\Services\SerpResultPersister;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Throwable;
|
||||
|
||||
class PollSerpCheck implements ShouldQueue
|
||||
{
|
||||
use Dispatchable,InteractsWithQueue,Queueable,SerializesModels;
|
||||
|
||||
public int $tries = 3;
|
||||
|
||||
public int $timeout = 60;
|
||||
|
||||
public array $backoff = [10, 60, 300];
|
||||
|
||||
public function __construct(public readonly string $checkUlid) {}
|
||||
|
||||
public function handle(SerpProviderRegistry $registry, SerpResultPersister $persister, ?OperationAuditLogger $audit = null): void
|
||||
{
|
||||
$audit ??= app(OperationAuditLogger::class);
|
||||
Cache::lock('serp-poll:'.$this->checkUlid, 75)->block(1, function () use ($registry, $persister, $audit) {
|
||||
$c = SerpCheck::where('ulid', $this->checkUlid)->firstOrFail();
|
||||
if (in_array($c->status, [SerpCheckStatus::Completed, SerpCheckStatus::Failed], true)) {
|
||||
return;
|
||||
}if ($c->status !== SerpCheckStatus::Running || ! $c->provider_reference) {
|
||||
$c->fail('provider_task_missing', 'SERP kontrolü tamamlanamadı.');
|
||||
|
||||
return;
|
||||
}$attempts = $c->provider_poll_attempts + 1;
|
||||
$c->forceFill(['provider_poll_attempts' => $attempts, 'provider_last_polled_at' => now(), 'provider_next_poll_at' => null])->save();
|
||||
if ($attempts > (int) config('serp.dataforseo.poll_max_attempts') || $c->provider_task_posted_at?->lt(now()->subMinutes((int) config('serp.dataforseo.max_task_age_minutes')))) {
|
||||
$c->fail('provider_task_expired', 'SERP kontrolü zamanında tamamlanamadı.');
|
||||
$audit->record('poll_exhausted', ['check_ulid' => $c->ulid, 'attempt' => $attempts, 'error_category' => 'poll_exhausted']);
|
||||
|
||||
return;
|
||||
}try {
|
||||
$p = $registry->resolve($c->provider);
|
||||
if (! $p instanceof AsyncSerpProvider) {
|
||||
throw new UnexpectedProviderResponseException('Provider does not support standard mode.');
|
||||
}$result = $p->collect($c->provider_reference, 10);
|
||||
$c->forceFill(['provider_status_code' => $result->statusCode])->save();
|
||||
if (! $result->ready) {
|
||||
$delay = (int) config('serp.dataforseo.poll_interval') * min($attempts, 4);
|
||||
$at = now()->addSeconds($delay);
|
||||
$c->forceFill(['provider_next_poll_at' => $at])->save();
|
||||
self::dispatch($c->ulid)->delay($at)->onQueue(config('serp.queue'));
|
||||
$audit->record('poll_not_ready', ['check_ulid' => $c->ulid, 'attempt' => $attempts]);
|
||||
|
||||
return;
|
||||
}$persister->complete($c, $result->response, ['provider_cost' => $c->provider_cost ?? $result->cost, 'provider_cost_currency' => $result->currency, 'provider_status_code' => $result->statusCode, 'provider_next_poll_at' => null]);
|
||||
$audit->record('poll_completed', ['check_ulid' => $c->ulid, 'attempt' => $attempts, 'result_count' => count($result->response->results)]);
|
||||
} catch (SerpProviderException $e) {
|
||||
$audit->record('poll_failed', ['check_ulid' => $c->ulid, 'attempt' => $attempts, 'error_category' => $e->safeCode()]);
|
||||
if ($e->retryable()) {
|
||||
throw $e;
|
||||
}$c->fail($e->safeCode(), $e->safeMessage());
|
||||
} catch (Throwable) {
|
||||
$c->fail('unexpected_error', 'SERP kontrolü tamamlanamadı.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function failed(?Throwable $e): void
|
||||
{
|
||||
$c = SerpCheck::where('ulid', $this->checkUlid)->first();
|
||||
if ($c && $e instanceof SerpProviderException) {
|
||||
$c->fail($e->safeCode(), $e->safeMessage());
|
||||
} elseif ($c) {
|
||||
$c->fail('job_failed', 'SERP kontrolü tamamlanamadı.');
|
||||
}
|
||||
}
|
||||
|
||||
public function tags(): array
|
||||
{
|
||||
return ['serp-check:'.$this->checkUlid, 'serp-mode:standard-poll'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user