Files
opensourcepos/app/Libraries/ImportBatchService.php
objecttothis 90e68714f0 feat(jobs): add batch-level import context and queue pause support
- Add import_batch_contexts table plus ImportBatchContext model so
  per-batch data (e.g. Items CSV attribute definitions) is stored
  once and referenced by context_id, instead of duplicated into
  every queued row's job payload.
- Extend queue_jobs, queue_jobs_failed, and new queue_paused_jobs
  tables with batch_id/context_id columns and FKs (ON DELETE
  RESTRICT) back to import_batch_contexts, so context rows cannot
  be purged while any job still references them.
- Introduce ImportBatchService.pushRow() to centralize queuing a
  batch row with batch/context stamping and priority; update
  Customers and Items controllers to use it instead of calling
  importBatch->create() and queue->push() separately.
- Add queue_paused_jobs table and Jobs::postPauseJobs()/pauseQueues()
  to move pending jobs out of queue_jobs into a paused table per
  queue (all core queues or a selected subset), leaving in-flight
  jobs untouched (issue #3833 pause/resume design).
- Change Jobs::getEditJob()/postSaveJob() routes to accept separate
  source/id path segments instead of a combined uid string.
- Add test coverage for ImportBatchContext, ImportBatchService, and
  ImportBatch (including purge-retains-while-referenced guards).

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-10-01 16:07:04 +04:00

83 lines
2.7 KiB
PHP

<?php
namespace App\Libraries;
use App\Models\ImportBatch;
use App\Models\ImportBatchContext;
/**
* Thin wrapper around the ImportBatch/ImportBatchContext models (issue #3833
* Phase 3), exposed as service('importBatch') so controllers pushing import
* jobs and the jobs themselves share one call surface instead of reaching
* into the models directly.
*/
class ImportBatchService
{
private ImportBatch $importBatch;
private ImportBatchContext $importBatchContext;
public function __construct()
{
$this->importBatch = model(ImportBatch::class);
$this->importBatchContext = model(ImportBatchContext::class);
}
/**
* Creates a new batch and returns its generated id. $context, when given,
* is stored once for the whole batch (e.g. attribute definitions for an
* Items CSV import) instead of being duplicated into every row's job.
*/
public function create(string $type, int $total, ?array $context = null): string
{
$batchId = uniqid('import_', true);
$this->importBatch->create($batchId, $type, $total);
if ($context !== null) {
$this->importBatchContext->create($batchId, $context);
}
return $batchId;
}
/**
* Fetches the batch-wide context snapshot stored at create(), decoded.
*/
public function getContext(string $batchId): ?array
{
return $this->importBatchContext->getByBatchId($batchId);
}
/**
* Pushes one row's job onto the queue and stamps the job with its
* batch_id and context_id as real columns (the vendor handler only knows
* about the JSON payload), so ImportBatch::purgeFinished() can cheaply
* check for still-referenced jobs instead of scanning payload JSON, and
* so the context_id foreign key protects import_batch_contexts rows.
*/
public function pushRow(string $queue, string $job, array $data, string $batchId, string $priority): void
{
$result = service('queue')->setPriority($priority)->push($queue, $job, $data);
db_connect()->table('queue_jobs')->where('id', $result->getJobId())->update([
'batch_id' => $batchId,
'context_id' => $this->importBatchContext->getIdForBatch($batchId),
]);
}
/**
* Atomically increments completed or failed for the batch.
*
* @return bool True if this call completed the batch.
*/
public function increment(string $batchId, bool $rowFailed): bool
{
return $this->importBatch->increment($batchId, $rowFailed);
}
public function purgeFinished(int $retentionDays): void
{
$this->importBatch->purgeFinished($retentionDays);
}
}