Skip to content

Releases: a8cteam51/a8csp-background-jobs-engine

v1.0.0-beta.4

v1.0.0-beta.4 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 07 Sep 19:56
v1.0.0-beta.4
bbb1b8d

Added

  • An execution object may declare the new RunCompletionInterface and receive on_completed( RunId $run_id, array $start_args, ?RunId $previous_completed_run_id ) when one of its runs completes. It removes the need to hand-assemble 'a8csp_bgje/completed/' . $scope . ':' . $name and re-derive that hook's argument order, which matters most to a Chunked Job, whose execution role has no last chunk to put post-queue work in.

    Registration subscribes the declaring object to that hook, so nothing about the hook changes: it still fires for every other listener, the payload is the same, and delivery stays at-least-once. Key what on_completed() does to the run identifier so a repeated delivery converges.

  • runs()->set_data() and runs()->get_data(), with the procedural a8csp_bgje_set_run_data() and a8csp_bgje_get_run_data(), store consumer values for the life of one run. A Chunked Job accumulates across chunks and has nowhere but storage to put what it accumulates; this holds it without a consumer inventing option rows keyed by run ID.

    The engine owns the lifetime. The whole row is dropped wherever the engine drops the run row — completed, failed, cancelled, superseded, and the corrupt rows maintenance removes without firing any hook — so a consumer cannot forget to clean up after a terminal path it did not think about, and cannot reconstruct that lifetime from terminal hooks because two of those deletions fire none. The hourly maintenance sweep collects data that outlives its run by any other route.

    Reading a key the run never stored returns null, which is a different answer from the empty array a key explicitly set to array() returns. A failed authoritative read returns storage_failed rather than null, so a database fault is not mistaken for "not generated yet".

    Run data is its own option family with its own ceiling; see Consumer limits. It is removed by uninstall and by wp a8csp-bgje reset.

  • schedules()->inspect(), and the procedural a8csp_bgje_inspect_schedules( $scope ), return the scope's persisted schedule registrations as plain arrays: name, identity, declared recurrence, next due, last fired, misfire and overlap counts, and whether a scheduling backend can currently see each occurrence.

    Synchronization happens on init, where a caller is rarely able to act on a refusal, and the engine does not log one. This answers the follow-up question — is the declaration actually in force — from a request that can do something about the answer. It reports facts and no verdict: what counts as wrong depends on what the caller declared, which the engine does not know.

Changed

  • runs()->last_completed() now answers for as long as the identity has ever completed. The run-history buffers are capped and hold every terminal outcome, so on an identity that fails often the last completion was carried out of them by later failures — at exactly the moment a caller most wants to know when the work last succeeded. The answer is now kept in a slot those buffers do not evict. The previous_completed_run_id argument of a8csp_bgje/completed/{identity} is frozen from the same slot, so the hook and the verb cannot disagree.

    The returned Run carries a new ?int $ended_at with the Unix timestamp the run reached its terminal state, so "when did this last succeed" is answerable without keeping a pointer of your own. It is null on projections that do not carry one, such as a dispatch result.

    wp a8csp-bgje runs list gains an ended column showing how long ago each history entry terminalized.

    A history row written by an earlier version carries neither the per-entry timestamp nor the slot. Its entries render ended as , and last_completed() answers such a row from the retained buffer with a null ended_at until the identity's next completion fills the slot — so the answer is never worse than it was before the upgrade.

v1.0.0-beta.3

v1.0.0-beta.3 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 10 Aug 11:14
v1.0.0-beta.3
b9b3362

Changed

  • A Chunked Job completes one scheduler delivery earlier once its queue drains, so its overlap lock is released sooner and a waiting dispatch is admitted where it previously saw the lane held.

    Cancelling a Chunked Job whose queue has drained is refused only while a continuation is actually pending to complete it. A run left without one is cancellable rather than reported as completing on its own.

  • Both dispatch entry points resolve a job's registration through one shared step, so an unregistered or incompletely registered job reports the same failure from either. The public API and observable behaviour are unchanged.

  • Boundary failures pass directly through the WordPress-facing adapters, reducing conversion without altering returned WP_Error codes, messages, data, or consumer behaviour.

  • Consumers see the same error codes, persisted values, command output and behaviour; three internal failure classifications that no operation could emit are no longer carried by the engine.

  • Development-reset command output is emitted directly. The public API, persisted row shapes, and observable behaviour are unchanged.

  • Execution-overlap lock rows now store only the owner run ID and latest heartbeat. Existing rows containing the former claim timestamp or other additional fields remain readable and are normalized on their next write.

    A lane holding such a row is therefore reported by wp a8csp-bgje locks list as owned or stale rather than malformed, is ineligible for malformed-lock reclamation, and no longer causes a maintenance warning.

  • Internal job registration, run persistence, schedule delivery and synchronization, lease and terminal-snapshot classification, the exact-write type layer, and run-kind lifecycle defaults are consolidated. The public API, persisted row shapes, and observable behaviour are unchanged.

  • Large Chunked Job queues no longer reserialize the whole growing queue for every generated or context-added chunk, reducing queue-generation and processing latency. A queue mutation whose exact size exceeds the limit only within the list-index envelope is rejected when the attempt commits instead of from the mutation call. That rejection stays terminal and non-retryable, but it reports payload_rejected at the scheduling stage rather than execution_failed at the execution stage, and carries no failed_chunk detail.

  • Lifecycle hook consumers retain the same names, payloads, order, and behaviour; event delivery is organised around a dedicated internal emission path for each lifecycle event.

  • Maintenance reads active-run values in bounded batches and exact-deletes a schema-invalid execution-overlap lock when no matching run is in Running state, while preserving the inspected lock when a matching Running run still depends on it or active-run inspection cannot safely classify the identity. A stale executing run, or a stale non-executing run with no pending action, is crash-reclaimed automatically from its run-row heartbeat behind a malformed lock; the subsequent lock phase reclaims the orphaned lock. While a non-executing row is fresh and preserved, wp a8csp-bgje runs cancel resolves it only when the identity has a live executable registration matching the persisted kind; otherwise cancellation returns unknown_job. Maintenance can still crash-reclaim the engine-installed job and chunked_job kinds after their heartbeat becomes stale without that consumer registration. Malformed-lock diagnostics expose only redacted raw-value correlation: a changed or absent generation loses the exact-delete fence silently, while an option-delete failure warns the operator.

    The documented manual lock-repair command has been removed. Operators who previously used it should expect the scheduled maintenance sweep to reclaim orphaned malformed lanes automatically; wp a8csp-bgje locks list remains available for diagnosis.

  • Malformed scheduler-wire deliveries are rejected before run or lock storage is accessed and now emit one warning with bounded identity and run-identifier correlation instead of a quiet debug stale-delivery message. Operators should correct the queued delivery bytes before retrying it.

  • Pending lifecycle delivery mode and timing are correlated within the engine's descriptor. This has no effect on the public API, stored rows, or observable behaviour.

  • Run status is a single vocabulary throughout the engine. The public cases, their persisted strings, consumer behaviour and command output are all unchanged.

  • The Action Scheduler backend checks readiness once per scheduling operation instead of re-checking each procedural function behind that gate. WP-Cron resolves one hook's occurrences through a single shared traversal. The scheduler composite is no longer itself a backend implementation, so the backend contract describes only the two backends that implement it. No supported behaviour changes.

  • The backend contract drops its pending-occurrence count, leaving the per-identity chain census as the one way to ask how many occurrences an identity has. No supported behaviour changes.

  • The internal overlap-lock claim contract reports malformed stored rows through its existing indeterminate outcome rather than a dedicated outcome. Dispatch failures and diagnostics are unchanged.

  • The supported Action Scheduler floor is 4.1.0. A site whose elected Action Scheduler is below that runs on WP-Cron instead, and its scheduling diagnostics flag the elected copy as unsupported. Action Scheduler elects the highest version among every bundled copy on the site, so the deciding copy is not necessarily the one installed beside this plugin. Upgrade Action Scheduler before upgrading this plugin: a recurring chain an older copy already holds keeps firing alongside the WP-Cron chain that replaces it, and hook-wide clearance is refused while an unsupported copy is present.

  • WP-CLI inspection behaviour, accepted arguments, and output stay stable while internal formatting and error paths use a smaller surface.

  • WP-CLI users need no changes: run-management and schedule-removal behaviour is preserved while each command addresses its dedicated runtime service directly.

Fixed

  • A Chunked Job whose queue is refused when the attempt commits now reports the chunk that was in flight in RunFailure::$details['failed_chunk'], matching every other terminal chunked failure that has one.
  • A cleanup-intent sweep that cannot read its cursor, enumerate intent rows, or read a page emits a warning naming the failed phase and directs operators to repair WordPress option reads before retrying the sweep. The two page-level warnings also report the cursor the pass had reached, so repeated failures can be told apart.
  • A cleanup intent for an unknown schedule chain is fenced by a random generation, so an hourly sweep and a concurrent delivery can no longer destroy each other's pending intent and leave a removed schedule's recurring occurrence in place. The durable intent row carries an integer generation rather than a creation timestamp.
  • A cleanup intent skipped because a read fails emits a warning naming the failed phase and what can retry the cleanup. A sweep whose cursor update is unconfirmed emits a warning naming the outcome that denied it — lost, write_failed, value_mismatch or delete_failed — and explaining that the next sweep resumes from the durable cursor state.
  • A dispatch that arrives as the previous run releases its overlap lane claims the available lane instead of failing with storage_failed. Each further attempt, and a lane that stays unclaimable across all of them, is published as a debug event, so both reach a8csp_bgje/log but not the default error-log sink.
  • A maintenance sweep reports an execution-overlap lock row it cannot read instead of silently skipping it, and directs operators to repair WordPress option reads before retrying the sweep.
  • A manual schedule dispatch that loses its occurrence-decision race reports admission_conflict rather than storage_failed. Both the manual-dispatch error and the scheduled-delivery log record state only that the delivery did not acquire the lease, which also changes what a held lease reports. The scheduled-delivery record for that state is a debug event, so it reaches a8csp_bgje/log but not the default error-log sink.
  • An authoritative option read that failed without a database error message is now reported as a storage failure instead of an absent row, so maintenance sweeps no longer treat an unanswered query as a completed scan.
  • Listing runs reports corrupt option rows that an exact-length database filter previously hid, and its warning states that the count covers every row sharing the identity's run option-name prefix, which a longer sibling identity also shares.
  • Schedule synchronization now directs failed registry reads to WordPress option-read repair, and cancelling a run logs a warning when pending deliveries cannot be cleared after its terminal state is committed.
  • Storage warnings identify the affected store, occurrence-lease failures identify the failed read or write, and their guidance either names the repair or explains that maintenance replays the effect without operator action. Unknown-schedule warnings publish intent_confirmed alongside converged so consumers can distinguish a confirmed intent from outstanding cleanup; they request scheduler removal for malformed keys only when cleanup remains necessary. Run creation returns distinct WP_Error messages that direct a conflicting run option to removal and an unanswered option write to WordPress storage repair. Failed-run help names table, CSV, JSON, count, and YAML output, and invalid formats use the same guidance as run and schedule lists.
  • Three ErrorCode case descriptions state what produces them. overlap_held is reported for a held overlap lock and never for a schedule's occurrence decision; admission_conflict means a lost admission race...
Read more

v1.0.0-beta.2

v1.0.0-beta.2 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 30 Jul 11:10
v1.0.0-beta.2
34c5f5c

Added

  • Lane takeover is covered by a test that holds a real dispatch inside the window between the two storage writes a takeover performs, so the one interleaving no previous test could reach is now exercised on every run.
  • New ErrorCode::AdmissionConflict (admission_conflict) tells a caller that admission lost a race and admitted nothing, as distinct from overlap_held, which means a still-running run owns the lane.

Changed

  • Dispatch now admits again on the caller's behalf when it loses an admission race, up to three attempts in total, so admission_conflict reaches a consumer only when a lane stayed contended throughout. A lost attempt leaves the lane as it found it and never reaches handler code, and an attempt that follows also takes custody of replaying a supersession the losing attempt could not restore. Under Replace this means a dispatch that lost a race can take the lane back from the one that just won it, which is what that policy asks for; under Reject a further attempt finds the live incumbent and reports overlap_held. Re-admission is logged at debug level. Scheduled occurrence delivery still admits once, because the scheduler redelivers a due occurrence on its own.

Fixed

  • Admission and takeover paths that could not admit a run reported overlap_held, which reads as "another run is doing this work" even when the lane was free; the eight such paths now return admission_conflict, so a caller that skips on overlap_held no longer drops work nobody is doing.

v1.0.0-beta.1

v1.0.0-beta.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Jul 22:00
v1.0.0-beta.1
06a796d

Added

  • First release.