74 lines
2.6 KiB
PHP
74 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Services\Billing\CatalogueSyncStatus;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Queue\Queueable;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Throwable;
|
|
|
|
/**
|
|
* Run `stripe:sync-catalogue` from the console, on the queue.
|
|
*
|
|
* Queued rather than done inside the Livewire call that asked for it: the
|
|
* command talks to Stripe, creates a Product per plan family and a Price per
|
|
* priced row on both tax treatments, and a first run on a full catalogue is
|
|
* seconds to minutes of network. A synchronous button would hold the request
|
|
* open for all of it and hand the operator a gateway timeout for an answer,
|
|
* with the run still going somewhere behind it.
|
|
*
|
|
* No agent, unlike UpdateChannel's requests: this needs nothing root can do and
|
|
* nothing outside the container. It is an artisan command this very application
|
|
* already ships, run by this very application's worker.
|
|
*
|
|
* NOT retried. Every other job here backs off and tries again; this one must
|
|
* not. The command is idempotent about Stripe objects, but a re-run after a
|
|
* failure would overwrite the recorded output with a second attempt's — and
|
|
* the output is the whole point: the refusal that names three columns to clear
|
|
* would be replaced by whatever the retry happened to say. An operator pressing
|
|
* the button again is the retry, and they will have read the first answer.
|
|
*/
|
|
class RunCatalogueSync implements ShouldQueue
|
|
{
|
|
use Queueable;
|
|
|
|
public int $tries = 1;
|
|
|
|
public function __construct(
|
|
public bool $dryRun,
|
|
public string $by,
|
|
) {}
|
|
|
|
public function handle(): void
|
|
{
|
|
$status = app(CatalogueSyncStatus::class);
|
|
|
|
try {
|
|
$exit = Artisan::call('stripe:sync-catalogue', $this->dryRun ? ['--dry-run' => true] : []);
|
|
$output = Artisan::output();
|
|
} catch (Throwable $e) {
|
|
// A throw is an outcome too, and it has to reach the page. Left
|
|
// uncaught this would be a failed job in a table nobody on this
|
|
// page can see, under a "sync running" note that never resolves.
|
|
$status->record(
|
|
ok: false,
|
|
dryRun: $this->dryRun,
|
|
output: $e->getMessage(),
|
|
by: $this->by,
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
$status->record(
|
|
ok: $exit === 0,
|
|
dryRun: $this->dryRun,
|
|
// Whole and unedited — see CatalogueSyncStatus. The command's own
|
|
// refusals are instructions, not statuses.
|
|
output: trim($output),
|
|
by: $this->by,
|
|
);
|
|
}
|
|
}
|