HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/app/Jobs/SendSingleMessage.php
<?php

namespace App\Jobs;

use App\Jobs\Concerns\JobControlAdapter;
use App\Jobs\Concerns\LogsJobFailure;
use App\Library\RouletteWheel;
use App\Library\Sending\Lifecycle\AutomationSendLifecycle;
use App\Library\Sending\SendContext;
use App\Library\Sending\SendPipeline;
use App\Model\AutomationEmail;
use App\Model\AutoTrigger;
use App\Model\Campaign;
use App\Model\Customer;
use App\Model\Subscriber;
use App\Model\Subscription;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

/**
 * Single-dispatch send job for automation triggers (one trigger action ->
 * one email). Sibling to App\Jobs\SendMessage — does NOT inherit from it
 * (constructor signatures differ).
 *
 * The pipeline does the same work as for campaign sends, just with the
 * AutomationSendLifecycle hooks: action->setSent on success, action->setError
 * on failure, action delay_note + release(600) on rate-limit (no batch path).
 *
 * Like its sibling, this Job does NOT implement JobControl directly — see
 * JobControlAdapter docblock. handle() wraps $this in an adapter for the
 * pipeline.
 */
class SendSingleMessage implements ShouldQueue
{
    use Batchable;
    use Dispatchable;
    use InteractsWithQueue;
    use LogsJobFailure;
    use Queueable;
    use SerializesModels;

    public $timeout = 900;
    public $maxExceptions = 1;
    public $failOnTimeout = true;

    // Sibling SendMessage carries a Campaign; this single-dispatch job
    // carries an AutomationEmail. The pipeline treats both as a "sendable"
    // (see SendContext::$campaign docblock).
    protected Campaign|AutomationEmail $campaign;
    protected Subscriber $subscriber;
    protected ?RouletteWheel $servers;
    protected ?Subscription $subscription;
    protected mixed $autoTriggerId;
    protected mixed $actionId;
    protected Customer $customer;

    public function __construct(
        Campaign|AutomationEmail $campaign,
        Subscriber $subscriber,
        RouletteWheel $servers,
        Subscription $subscription = null,
        $autoTriggerId = null,
        $actionId = null,
    ) {
        $this->campaign = $campaign;
        $this->subscriber = $subscriber;
        $this->servers = $servers;
        $this->subscription = $subscription;
        $this->autoTriggerId = $autoTriggerId;
        $this->actionId = $actionId;
        $this->customer = $campaign->customer;
    }

    public function retryUntil(): \DateTime
    {
        return now()->addDays(30);
    }

    public function handle(): void
    {
        $this->customer->setUserDbConnection();

        $connection = $this->customer->hasLocalDb() ? $this->customer->db_connection : 'mysql';
        $trigger = AutoTrigger::on($connection)->find($this->autoTriggerId);
        if ($trigger === null) {
            throw new \Exception(
                "Cannot find trigger {$this->autoTriggerId} (DB connection ".\DB::connection()->getName().')'
            );
        }

        $ctx = new SendContext(
            campaign: $this->campaign,
            subscriber: $this->subscriber,
            servers: $this->servers,
        );

        $lifecycle = new AutomationSendLifecycle($trigger, $this->actionId, $this->subscription);

        // JobControlAdapter bridges this Job's Laravel trait methods to the
        // pipeline's strict-typed JobControl interface. See adapter docblock.
        $control = new JobControlAdapter($this);

        app(SendPipeline::class)->run($ctx, $lifecycle, $control);
    }
}