DICTIONARY_KEY
DICTIONARY_KEY = 'strata.dictionary.trained'
State key holding when the dictionary pass last ran.
Drives everything that has no request to run in.
Cron is what makes capture into a backup on a site nobody is watching. A busy site also flushes from the request that filled the window, but a quiet one may go hours between writes, and the age bound exists precisely so those few writes still reach the store.
Four things run here, in this order and for these reasons:
No stage can stop cron. A cron hook that throws stops every later hook in the queue, so a storage outage would take the site's search indexing and cache warming down with it. Each stage is caught separately, so one failing does not skip the others either.
The engine arrives rather than the eight things it builds, and that is load bearing. Every
stage is assembled from configuration and assembling one can refuse: encryption is on by default
with no key, so Engine::flusher() throws on a site nobody has configured yet. Drupal resolves a
cron hook's service inside ModuleHandler::invokeAllWith(), which runs before the per-module
try/catch in Cron::invokeCronHandlers() and before this class can check anything. Taking the
stages as constructor arguments therefore skipped every module's cron and left the cron lock held
for its full 900 seconds. Each stage resolves what it needs inside its own guard instead.
$engine : \Drupal\strata\Engine
$scope : \Drupal\strata\Capture\CaptureScope
$lease : \Drupal\strata\Flush\Lease
__construct(\Drupal\strata\Engine $engine, \Drupal\strata\Capture\CaptureScope $scope, \Drupal\strata\Flush\Lease $lease, \Psr\Log\LoggerInterface $logger, \Drupal\Core\State\StateInterface $state, \Drupal\Core\Config\ConfigFactoryInterface $configFactory, int $dictionaryInterval = \self::DICTIONARY_INTERVAL) : mixed
Constructs the cron capture.
| \Drupal\strata\Engine | $engine | Builds each stage on demand. Deliberately not the stages themselves; see the class docblock. |
| \Drupal\strata\Capture\CaptureScope | $scope | Decides whether capture is on at all. |
| \Drupal\strata\Flush\Lease | $lease | Collected on each run so an abandoned lease cannot block a flush forever. |
| \Psr\Log\LoggerInterface | $logger | Records a stage that could not run. |
| \Drupal\Core\State\StateInterface | $state | Remembers when the dictionary pass and the last drill ran. |
| \Drupal\Core\Config\ConfigFactoryInterface | $configFactory | Decides whether the anomaly and drill stages are on, and how often the drill runs. |
| int | $dictionaryInterval | Seconds between dictionary passes. |
assessBudget() : \Drupal\strata\Budget\BudgetAssessment|null
Prices the month against the ceilings, if any are set.
Skipped outright when neither ceiling is configured, which is the shipped state: reading the stat table and the frame index every cron run to price a site against no ceiling is two queries for an answer that cannot change anything.
The reading is announced and recorded rather than enforced here. What a rung means is applied
where the work happens - EscalationLadder::pausesRealm() in the capture scope and
stopsEverything() on the flush path - and both read the finding this stage leaves behind.
The reading, or NULL when no ceiling is set.
repair() : \Drupal\strata\Health\RepairReport|null
Runs the repair a finding's rung names, if automatic repair is on.
This is the only unattended caller of the ladder. Every rung it can take reconstructs derived
state from data that still exists, so the worst case of running one wrongly is wasted work;
quarantine and refuse remove a restore target and are refused here by name.
What was repaired, or NULL when the stage is off.