NORMAL
NORMAL = 'normal'
Under budget.
What Strata gives up as a budget fills, and the order it gives it up in.
Rungs run lowest first, cheapest and most reversible first, and a reading only ever moves one rung at a time in either direction. A budget that keeps overshooting climbs at a rate an operator can watch, and one that comes back under walks down on its own instead of staying clamped until somebody notices.
The line that matters sits between reduce and pause. Everything at or below reduce keeps every realm covered and only trades away depth of history, so the worst case is a shorter window to restore from. Pause and stop drop data that is never captured and therefore can never be restored, which is the ladder giving up the thing a backup exists to provide.
The realms that go first are the ones a site can rebuild from somewhere else: files usually exist in the media library's own storage, ephemeral state rebuilds itself, and code comes from the release artifact. What stays is what only the database holds.
PAUSED_REALMS = [\Drupal\strata\Journal\Realm::FILE->value, \Drupal\strata\Journal\Realm::EPHEMERAL->value, \Drupal\strata\Journal\Realm::CODE->value]
The realms capture drops at the pause rung.
Held as realm values rather than cases so a rung read back out of state can be compared without being parsed first.
rungFor(float $usedFraction) : string
The rung a projected usage lands on.
Read with >= at every step, so a fraction above STOP_AT lands on stop rather than falling through. A negative fraction, or one that is not a number at all, lands on normal: neither is evidence of overspending, and neither should stop a backup.
| float | $usedFraction | Projected usage divided by the ceiling. 1.0 is exactly the ceiling. |
A rung name from RUNGS.
cap(string $measured, string $allowed) : string
The measured rung, held to the highest one the site allows.
budget.action is what the operator chose to happen at the ceiling, and the thresholds above
are what the overspend measures. Without this the two disagree: a site that asked for Warn Only
has its capture stopped at 1.5x, which is the opposite of what it said. So the choice is a
ceiling on the ladder rather than a separate setting.
| string | $measured | The rung EscalationLadder::rungFor() returned. |
| string | $allowed | The highest rung configuration permits. A value not on the ladder allows everything, since refusing to act on an unreadable setting would mean ignoring a real overspend. |
Whichever of the two is lower.
escalate(string $rung) : string
One rung up, saturating at the top.
Saturation rather than an exception, because escalation runs on the path where a budget has already been exceeded; throwing there adds a failure on top of the one being reported.
| string | $rung | Current rung. |
The next rung up, the same rung at the top, or the lowest rung when $rung is not on the ladder at all.
decay(string $rung) : string|null
One rung down, or NULL at the bottom.
NULL is the signal to stop tracking the budget state entirely rather than to store normal forever; a site that has never been near its ceiling should carry no rung at all.
| string | $rung | Current rung. |
The rung below, or NULL when already at the bottom or not on the ladder.
pausesRealm(string $rung, string $realm) : bool
Whether capture of one realm is suspended at this rung.
An unrecognised rung suspends nothing. The ladder is driven by BudgetGuard, which only ever produces names from RUNGS, so the only way to arrive here with something else is state that has been corrupted or written by a version that disagrees; stopping a backup on the strength of that costs more than the overspend it might have prevented.
| string | $rung | The rung in force. |
| string | $realm | A realm value, as Realm stores it. |
TRUE when nothing in that realm should be captured.