121 lines
3.3 KiB
PHP
121 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Mail\Jobs\CodeGenerationSucceed;
|
|
use App\Mail\Jobs\JobFailed;
|
|
use App\Models\Code;
|
|
use App\Models\Settings;
|
|
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Queue\Queueable;
|
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Throwable;
|
|
|
|
class ProcessUniqueCode implements ShouldBeUnique, ShouldQueue
|
|
{
|
|
use Queueable;
|
|
|
|
/**
|
|
* The number of seconds the job can run before timing out.
|
|
*
|
|
* 7200 seconds (2 hours)
|
|
*
|
|
* @var int
|
|
*/
|
|
public $timeout = 7200;
|
|
|
|
/**
|
|
* Create a new job instance.
|
|
*
|
|
* @param int $amount Amount of code to generate.
|
|
* @param int $length Length of each code to generate.
|
|
*/
|
|
public function __construct(protected int $amount, protected int $length)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Execute the job.
|
|
*/
|
|
public function handle(): void
|
|
{
|
|
DB::transaction(function (): void {
|
|
// ! Le premier code commence à 1
|
|
$last_id = (Code::query()->max('id') ?? 0) + 1;
|
|
|
|
/** @var Settings $settings */
|
|
$settings = resolve(Settings::class);
|
|
|
|
$maxSQLPlaceholders = 65535;
|
|
|
|
$insertColumns = collect(DB::getSchemaBuilder()
|
|
->getColumnListing(new Code()->getTable()))
|
|
->reject(fn ($name): bool => in_array($name, ['id', 'code_exported']))->count() + 1;
|
|
|
|
/**
|
|
* Nombre d'insertions max sur un seule requète
|
|
*/
|
|
$perPage = \floor($maxSQLPlaceholders / $insertColumns);
|
|
|
|
/**
|
|
* Nombre de page totale à insérer.
|
|
*/
|
|
$totalPages = \ceil($this->amount / $perPage);
|
|
|
|
$totalGeneratedInserts = 0;
|
|
|
|
for ($currentPage = 1; $currentPage <= $totalPages; $currentPage++) {
|
|
$inserts = [];
|
|
$insertToGenerate = min($perPage, $this->amount - $totalGeneratedInserts);
|
|
do {
|
|
$inserts[] = [
|
|
'id' => $last_id++,
|
|
'date_creation' => now()->format('Y-m-d'),
|
|
];
|
|
} while (($totalGeneratedInserts < $this->amount) && --$insertToGenerate);
|
|
|
|
// * Mass insert
|
|
Code::query()->insert($inserts);
|
|
|
|
$totalGeneratedInserts += count($inserts);
|
|
}
|
|
|
|
// * Fin de la génération.
|
|
Mail::to(config('mail.admin'))->send(new CodeGenerationSucceed(
|
|
$this->amount,
|
|
$settings->name
|
|
));
|
|
});
|
|
}
|
|
|
|
/**
|
|
* In case of job failure
|
|
*/
|
|
public function failed(Throwable $exception): void
|
|
{
|
|
Mail::to(config('mail.admin'))->send(
|
|
new JobFailed(self::class, [
|
|
'message' => $exception->getMessage(),
|
|
'trace' => $exception->getTraceAsString(),
|
|
])
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the middleware the job should pass through.
|
|
*
|
|
* @return array<int, object>
|
|
*/
|
|
public function middleware(): array
|
|
{
|
|
return [
|
|
new WithoutOverlapping('code_generation')
|
|
->releaseAfter(60),
|
|
];
|
|
}
|
|
}
|