fix: queue Mailwizz sync by subscriber id and skip stale payloads

Serialize only the subscriber primary key to avoid ModelNotFound on
unserialize when the row is gone. Guard handle() when subscriberId is
missing after old payload shapes.

Made-with: Cursor
This commit is contained in:
2026-04-05 13:33:50 +02:00
parent 7eda51f52a
commit 627edbbb83

View File

@@ -14,7 +14,6 @@ use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit; use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use RuntimeException; use RuntimeException;
use Throwable; use Throwable;
@@ -24,7 +23,6 @@ class SyncSubscriberToMailwizz implements ShouldBeUnique, ShouldQueueAfterCommit
use Dispatchable; use Dispatchable;
use InteractsWithQueue; use InteractsWithQueue;
use Queueable; use Queueable;
use SerializesModels;
/** /**
* Seconds before the unique lock expires if the worker dies before releasing it. * Seconds before the unique lock expires if the worker dies before releasing it.
@@ -38,23 +36,42 @@ class SyncSubscriberToMailwizz implements ShouldBeUnique, ShouldQueueAfterCommit
*/ */
public array $backoff = [10, 30, 60]; public array $backoff = [10, 30, 60];
public function __construct(public Subscriber $subscriber) /**
* Set in the constructor for new jobs. Remains null when an old queue payload (presubscriber-id refactor) is unserialized.
*/
public ?int $subscriberId = null;
/**
* @param Subscriber|int $subscriber Model is accepted when dispatching; only the id is serialized for the queue.
*/
public function __construct(Subscriber|int $subscriber)
{ {
$this->subscriberId = $subscriber instanceof Subscriber
? (int) $subscriber->getKey()
: $subscriber;
$this->onQueue('mailwizz'); $this->onQueue('mailwizz');
} }
public function uniqueId(): string public function uniqueId(): string
{ {
return (string) $this->subscriber->getKey(); return $this->subscriberId !== null
? (string) $this->subscriberId
: 'stale-mailwizz-sync-payload';
} }
public function handle(): void public function handle(): void
{ {
if ($this->subscriberId === null) {
Log::notice('SyncSubscriberToMailwizz: skipped job with missing subscriber id (stale queue payload). Clear the queue or re-dispatch sync jobs.');
return;
}
try { try {
$this->runSync(); $this->runSync();
} catch (Throwable $e) { } catch (Throwable $e) {
Log::error('SyncSubscriberToMailwizz: integration failed; subscriber remains local (use admin resync if needed)', [ Log::error('SyncSubscriberToMailwizz: integration failed; subscriber remains local (use admin resync if needed)', [
'subscriber_id' => $this->subscriber->id, 'subscriber_id' => $this->subscriberId,
'message' => $e->getMessage(), 'message' => $e->getMessage(),
]); ]);
} }
@@ -64,7 +81,7 @@ class SyncSubscriberToMailwizz implements ShouldBeUnique, ShouldQueueAfterCommit
{ {
$subscriber = Subscriber::query() $subscriber = Subscriber::query()
->with(['preregistrationPage.mailwizzConfig']) ->with(['preregistrationPage.mailwizzConfig'])
->find($this->subscriber->id); ->find($this->subscriberId);
if ($subscriber === null) { if ($subscriber === null) {
return; return;
@@ -115,7 +132,7 @@ class SyncSubscriberToMailwizz implements ShouldBeUnique, ShouldQueueAfterCommit
public function failed(?Throwable $exception): void public function failed(?Throwable $exception): void
{ {
Log::error('SyncSubscriberToMailwizz failed', [ Log::error('SyncSubscriberToMailwizz failed', [
'subscriber_id' => $this->subscriber->id, 'subscriber_id' => $this->subscriberId,
'message' => $exception?->getMessage(), 'message' => $exception?->getMessage(),
]); ]);
} }