fix: isolate public subscribe from integration job failures

Queue Weeztix/Mailwizz after the HTTP response and catch dispatch errors.
Jobs log Mailwizz/Weeztix API failures without rethrowing so sync driver
and terminating callbacks do not surface 500s after a successful create.

Add JS fallback for non-JSON error responses, deployment note, and a
regression test for failing Mailwizz under QUEUE_CONNECTION=sync.

Made-with: Cursor
This commit is contained in:
2026-04-05 11:47:59 +02:00
parent d802ce2a7c
commit de83a6fb76
6 changed files with 102 additions and 27 deletions

View File

@@ -52,27 +52,42 @@ final class IssueWeeztixCouponForSubscriber implements ShouldBeUnique, ShouldQue
public function handle(): void
{
$subscriber = Subscriber::query()
->with(['preregistrationPage.weeztixConfig', 'preregistrationPage.mailwizzConfig'])
->find($this->subscriber->id);
try {
$subscriber = Subscriber::query()
->with(['preregistrationPage.weeztixConfig', 'preregistrationPage.mailwizzConfig'])
->find($this->subscriber->id);
if ($subscriber === null) {
return;
if ($subscriber === null) {
return;
}
$page = $subscriber->preregistrationPage;
if ($page === null) {
return;
}
$config = $page->weeztixConfig;
$couponMissing = ! is_string($subscriber->coupon_code) || $subscriber->coupon_code === '';
if ($couponMissing && $this->weeztixCanIssueCodes($config)) {
$this->tryAttachWeeztixCouponCode($subscriber, $config);
}
$this->dispatchMailwizzIfNeeded($subscriber);
} catch (Throwable $e) {
Log::error('IssueWeeztixCouponForSubscriber: handle failed', [
'subscriber_id' => $this->subscriber->id,
'message' => $e->getMessage(),
]);
$subscriber = Subscriber::query()
->with(['preregistrationPage.mailwizzConfig'])
->find($this->subscriber->id);
if ($subscriber !== null) {
$this->dispatchMailwizzIfNeeded($subscriber);
}
}
$page = $subscriber->preregistrationPage;
if ($page === null) {
return;
}
$config = $page->weeztixConfig;
$couponMissing = ! is_string($subscriber->coupon_code) || $subscriber->coupon_code === '';
if ($couponMissing && $this->weeztixCanIssueCodes($config)) {
$this->tryAttachWeeztixCouponCode($subscriber, $config);
}
$this->dispatchMailwizzIfNeeded($subscriber);
}
public function failed(?Throwable $exception): void
@@ -97,7 +112,14 @@ final class IssueWeeztixCouponForSubscriber implements ShouldBeUnique, ShouldQue
$page?->loadMissing('mailwizzConfig');
if ($page?->mailwizzConfig !== null) {
SyncSubscriberToMailwizz::dispatch($subscriber->fresh());
try {
SyncSubscriberToMailwizz::dispatch($subscriber->fresh());
} catch (Throwable $e) {
Log::error('IssueWeeztixCouponForSubscriber: could not queue Mailwizz sync', [
'subscriber_id' => $subscriber->id,
'message' => $e->getMessage(),
]);
}
}
}

View File

@@ -47,6 +47,18 @@ class SyncSubscriberToMailwizz implements ShouldBeUnique, ShouldQueueAfterCommit
}
public function handle(): void
{
try {
$this->runSync();
} catch (Throwable $e) {
Log::error('SyncSubscriberToMailwizz: integration failed; subscriber remains local (use admin resync if needed)', [
'subscriber_id' => $this->subscriber->id,
'message' => $e->getMessage(),
]);
}
}
private function runSync(): void
{
$subscriber = Subscriber::query()
->with(['preregistrationPage.mailwizzConfig'])