use ProjectSaturnStudios\ConsumptionEngine\ConsumptionEngine;
use ProjectSaturnStudios\ConsumptionEngine\Enums\TaskExecutionStatus;
$filename = null; // input: null or basename under the task folder
$status = app(ConsumptionEngine::class)->executeTask('catalog-products', $filename);
// on success, $filename is filled with the full storage path by reference
if ($status === TaskExecutionStatus::TASK_STARTED) {
// job is on data-proc
}
protected function getContents(): ?array
{
return array_map(function (array $row) {
$row['uuid'] = /* deterministic id for this row */;
return $row;
}, parent::getContents());
}
namespace App\Jobs\Consumption\Example;
use Illuminate\Support\Collection;
use ProjectSaturnStudios\ConsumptionEngine\Jobs\ConsumptionJob;
use ProjectSaturnStudios\ConsumptionEngine\Events\Realtime\TaskDataValidationStarted;
use ProjectSaturnStudios\ConsumptionEngine\Events\Realtime\TaskWarning;
class ConsumeExampleData extends ConsumptionJob
{
protected function validateRecords(Collection &$raw_contents_sorted): void
{
$this->fireEvent(new TaskDataValidationStarted(
$this->channel, $this->filename, $this->task, count($raw_contents_sorted)
));
$results = collect();
foreach ($raw_contents_sorted as $uuid => $content) {
try {
// Validate / build DTO...
$results->put($uuid, $content);
$this->audit_log->put($uuid, ['status' => 'valid']);
} catch (\Throwable $e) {
$this->audit_log->put($uuid, [
'status' => 'invalid',
'error' => $e->getMessage(),
]);
$this->fireEvent(new TaskWarning(
$this->channel, $this->filename, $this->task, "Invalid: {$e->getMessage()}"
));
}
}
// Replace with processable rows only (invalid rows stay in audit_log)
$raw_contents_sorted = $results;
}
protected function setRecordActions(Collection &$raw_processable_contents): void
{
// Load existing domain state yourself, then decide create / update / none.
$raw_processable_contents = $this->mapRecordsWithProgress(
$raw_processable_contents,
function ($uuid, $content, Collection $results): void {
$entry = $this->audit_log->get($uuid) ?? [];
$entry['action'] = 'create'; // or update / none
$this->audit_log->put($uuid, $entry);
$results->put($uuid, $content);
}
);
}
protected function consumeNewRecords(Collection $raw_processable_contents): void
{
$this->consumeActionRecords($raw_processable_contents, 'create', function ($dto): void {
event_command(/* your create command */, []);
});
}
protected function updateRecords(Collection $raw_processable_contents): void
{
$this->updateActionRecords($raw_processable_contents, 'update', function ($dto): void {
event_command(/* your update command */, []);
});
}
}
bash
php artisan horizon
# or restart after config changes:
php artisan horizon:terminate
bash
# oldest unconsumed file for the task
php artisan consume catalog-products
# specific file — basename only (folder comes from config/tasks.php)
php artisan consume catalog-products --file=cp_2024-05-30.csv