Commit Graph
10 Commits
Author SHA1 Message Date
objecttothis be5dbc5531 feat(jobs): add per-job pause functionality to manage grid
- Introduce pause icon for individual jobs in the manage grid.
- Add `Jobs::postPauseJob` controller method to handle pausing of single jobs.
- Update tabular helper to include pause link for pending jobs.
- Extend language files with translation for "pause job."
- Implement client-side logic for pausing jobs with AJAX in manage_grid.js.
- Update CSV import logic to correctly handle escaped headers.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-10-01 16:38:27 +04:00
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
objecttothis 8f6b4d4b45 refactor(jobs): rename job view/save routes and polish Jobs lang strings
- Rename Jobs::getView to getEditJob and Jobs::postSave to
  postSaveJob for clearer, action-specific route naming
- Update tabular_helper edit link and job_edit form action to
  use new jobs/editJob and jobs/saveJob routes
- Add confirm_delete, confirm_restore, and no_jobs_to_display
  strings to Jobs language file for upcoming bulk actions UI
- Fix alignment/formatting of Jobs language array entries

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-10-01 12:46:36 +04:00
objecttothis 5bd466d57b feat(jobs): add Jobs Manage grid CRUD and requeue actions
Extend Jobs controller to support full lifecycle management of
queued/failed jobs from the Manage tab UI.

- Add getView/postSave to edit a pending/reserved job's payload,
  priority, and available_at via modal (job_edit view)
- Add getSearch to back the AJAX-driven jobs table, using new
  JobQueueManage model for search/sort/pagination and payload
  decoding
- Add postDelete to bulk-delete pending/failed jobs, blocking
  deletion of reserved (in-progress) jobs
- Add postProcessJob to manually run a single job immediately,
  requeuing failed jobs back into queue_jobs first via new
  requeueFailedJob helper
- Add splitUid helper to parse "source:id" row identifiers shared
  across the new endpoints
- Extend queue_jobs_failed migration with attempts column since
  codeigniter4/queue's DatabaseHandler::failed() doesn't carry it
  over; BoundedQueueWorker now records it on failure so Manage
  grid can show real error counts

BREAKING CHANGE: queue_jobs_failed table gains required attempts
column; run new migration before deploying.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-10-01 12:04:36 +04:00
objecttothisandClaude Sonnet 5 4fa7db6da7 feat(jobs): add background job queue execution engine
Adds the queue_jobs, queue_jobs_failed, and job_throttles tables and wires
up BoundedQueueWorker (deadline-bounded queue draining, shared by the
JobRunner filter for web/auto mode and the manual "Process Jobs" UI) gated
by JobThrottleGate. Adds retry limit, retention, and auto-purge settings
to the Job Queue settings tab, and a manual per-queue processing UI on the
Utilities tab. Also adds a second-granularity throttle period and
BaseOsposJob as the shared base for core queue jobs.

This is issue #3833 Phase 2 — no real job types are queued yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 20:00:27 +04:00
objecttothis 14b06eea30 feat(jobs): add task time warning threshold setting
Introduce a soft, log-only per-task time budget (jobs_task_max_seconds)
separate from the existing web request budget (jobs_web_max_seconds),
since PHP cannot preempt a running task mid-execution.

- Config: add taskMaxSeconds default (30s) to app/Config/Jobs.php
- Controller: validate and persist task_max_seconds in
  Jobs::postSaveSettings
- BoundedTaskRunner: accept taskMaxSeconds, measure task runtime via
  microtime, log a warning when a task exceeds the threshold
- JobRunner: read jobs_task_max_seconds from config and pass it to
  BoundedTaskRunner
- Migration: add AddJobsTaskMaxSecondsConfigKey to seed default
  app_config value
- Language: add en strings for label, validation message, and
  enabled/disabled tooltips
- View: add task_max_seconds form field to settings_config.php,
  wired to same web-mode enable/disable toggle as web_max_seconds
- Tests: update JobsControllerTest to cover new field in save/
  validation scenarios

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-09-23 13:22:16 +04:00
objecttothis 171dd056b3 fix(jobs): validate all throttles before saving any
Bug: saveThrottles validated and saved throttles in same loop.
Invalid entry mid-loop stopped processing but left already-saved
throttles committed, and omitted throttles could still get deleted
via notToDelete tracking — partial/inconsistent state on failure.

- app/Controllers/Jobs.php: split into two passes — validate all
  throttleData entries first; on any invalid entry, roll back
  transaction and return failure immediately before touching DB.
  Only save/delete once full payload validated. Drop now-redundant
  $success flag folded into invalid-entry early return.
- tests/Controllers/JobsControllerTest.php: add test asserting
  existing throttles stay unchanged in DB when payload contains
  invalid throttle data.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-09-17 16:22:55 +04:00
objecttothis 9f70efb592 fix(Jobs): anchor throttle field regex to prevent id extraction bugs
Throttle POST field parsing used preg_replace with an unanchored
lazy pattern to pull numeric ids out of field names, which could
mis-extract or silently fall through on unexpected key formats.

- Replace preg_replace('/.*?_(\d+)$/', ...) with preg_match against
  an anchored pattern ('/^throttle_count_(\d+)$/' and
  '/^throttle_period_(\d+)$/') in app/Controllers/Jobs.php
- Only process the key when the anchored pattern actually matches,
  avoiding bogus $throttleId values feeding $arraySave/$notToDelete

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-09-17 16:20:26 +04:00
objecttothis bb99a22f59 fix(job-throttle): return saved throttle id to prevent unintended deletion
- JobThrottle::saveValue now returns int throttle_id instead of bool:
  new inserts return the DB-generated insertID, updates return the
  existing throttleId.
- Jobs controller collects saved ids into $notToDelete using the
  returned value, so newly inserted throttles are correctly tracked.

Fixes bug where newly inserted throttles had no id captured,
causing them to be wrongly deleted in the post-save cleanup step.

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-09-17 15:29:58 +04:00
objecttothis b7506e58dc feat(jobs): add web-triggered job scheduler with settings UI
Introduce a lightweight job scheduling system built on CI4 Tasks,
allowing due tasks to run via normal web traffic instead of relying
solely on external cron/Task Scheduler processes.

- Add JobRunner filter: runs TaskRunner after response send via
  shutdown function, throttled per-minute via cache, respects
  jobs_mode config ('auto'/'web'/'manual') and max-seconds budget
- Register jobrunner filter globally (app/Config/Filters.php),
  disabled during testing to avoid heartbeat log spam
- Add Config/Tasks.php with jobs_heartbeat scheduled task (debug
  log every minute) as scaffolding for future job commands
- Add Config/Jobs.php for mode/webMaxSeconds defaults
- Add Jobs controller + views (manage, settings_config,
  utilities_config, partial/job_throttles) for configuring mode,
  web max seconds, and per-period throttles; process-all/selected
  actions stubbed for a later phase
- Add gulp task to copy jobs.svg menubar icon
- Fix tooltip clipping: use container: 'body' for bootstrap
  tooltips and add max-width/text-align rules for tooltip-inner /
  ui-tooltip in ospos.css
- Fix missing closing div in partial/footer.php layout

Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-09-17 15:11:54 +04:00