> For the complete documentation index, see [llms.txt](https://quantumphp.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantumphp.gitbook.io/docs/packages/cron/architecture.md).

# Architecture

## Main pieces

The package has four public building blocks:

* `CronManager` loads task files and runs matching tasks
* `CronTask` wraps a task name, a cron expression, and a callback
* `Schedule` builds `CronTask` instances with a fluent API
* `CronLock` uses lock files plus `flock()` to prevent overlapping runs

## Task discovery

`CronManager` resolves its task directory in this order:

1. constructor argument
2. `cron_config('path')`
3. `base_dir()/cron`

`loadTasks()` scans that directory for `*.php` files and requires each file.

Each required file must return either:

* a ready-made `CronTaskInterface` object, or
* an array definition with `name`, `expression`, and `callback`

Array definitions are converted into `CronTask` objects before execution.

## Due-check and execution flow

`runDueTasks()` loads tasks, asks each task `shouldRun()`, and sends due tasks through the same runner used by `runTaskByName()`.

The manager keeps execution counters in one stats array:

* `total`
* `executed`
* `skipped`
* `failed`
* `locked`

Those counters live on the manager instance. If you reuse the same instance for multiple runs, stats accumulate instead of resetting.

## Lock lifecycle

Each task run creates a `CronLock` keyed by the task name.

Lock files live under the configured lock directory and use a sanitized version of the task name. Empty or fully sanitized-away names fall back to `default`.

Lock behavior is:

* constructor ensures the lock directory exists
* constructor also cleans up stale `*.lock` files older than `max_lock_age`
* `acquire()` creates or opens the task lock file and tries a non-blocking exclusive lock
* a successful lock writes the current Unix timestamp into the file
* `release()` unlocks, closes, and removes the lock file

`isLocked()` is a read-style probe. It checks whether another process currently holds the lock, but it does not delete files on its own.

## Force mode

When you run `runDueTasks(true)` or `runTaskByName($name, true)`, the manager skips lock acquisition entirely.

That also means the `finally` block does not release a lock for that run. Force mode is meant to bypass the lock system, not refresh or clean it up.

## Logging behavior

The manager logs start, skip, success, and failure events through `LoggerFactory::get(LoggerType::SINGLE)`.

If the logger cannot be resolved, the package falls back to `error_log()`.

## Failure boundaries

There are two different failure layers:

* task-definition and setup failures throw `CronException`
* task callback failures are caught inside the manager, counted, and logged

That split matters in production: a broken task file stops the run setup, while a failing due task does not stop other due tasks from being processed.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://quantumphp.gitbook.io/docs/packages/cron/architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
