\Drupal\strata\Health MemoryHealthLedger

A health ledger held in process memory.

This is the ledger a single run uses: a cron sweep that records what it found, decides what to do about it and reports at the end, all inside one request. It keeps no state between processes, which makes it the right thing for tests and for a one-shot sweep and the wrong thing for anything that has to remember across a deploy.

What it does share with a durable ledger is the bound. Retention is capped per code, at MAX_PER_CODE by default, for the same reason Finding clamps its context: the unbounded field here is scope - every frame hash is a new one - and a code that flaps produces a new scope on every pass. Trusting a purge to run is how a table nobody looks at becomes the largest thing in the database. When the cap is reached the oldest finding for that code is dropped, because the most recent occurrences are the ones that describe what is happening now.

Summary

Methods
Properties
Constants
__construct
record
open
summary
resolve
purge
rungFor
setRung
No public properties found
MAX_PER_CODE
No protected methods found
No protected properties found
No protected constants found
settle
now
maxPerCode
clock
entries
rungs
sequence
No private constants found

Constant

MAX_PER_CODE

MAX_PER_CODE = 50

Findings retained per code before the oldest is dropped.

Properties

$maxPerCode

$maxPerCode : int

How many findings to keep per code.

Type

int —

$clock

$clock : \Closure

Returns the current unix timestamp.

Type

Closure

$entries

$entries : array>

Retained findings, keyed by code, oldest first within each code.

Type

array<string, array<int, Finding, at: int, seq: int}>> —

$rungs

$rungs : array

The rung each code has been explicitly moved to.

Type

array<string, string> —

$sequence

$sequence : int

Monotonic counter giving every recorded finding a total order.

Timestamps tie constantly - a sweep records everything it found in the same second - so the clock alone cannot order the ledger for a reader.

Type

int —

Methods

__construct()

__construct(int  $maxPerCode = \self::MAX_PER_CODE, callable|null  $clock = null) : mixed

Constructs the ledger.

Parameters

int $maxPerCode

Findings retained per code.

callable|null $clock

Returns a unix timestamp as an int. NULL uses time().

Throws

\InvalidArgumentException

When $maxPerCode is below 1, which would make record() a no-op that still reported success.

Returns

mixed —

record()

record(\Drupal\strata\Health\Finding  $finding) : void

Records one finding.

Parameters

\Drupal\strata\Health\Finding $finding

What a tripwire noticed.

Returns

void —

open()

open() : \Drupal\strata\Health\Finding[]

Every finding still held, oldest first.

Returns

\Drupal\strata\Health\Finding[] —

The open findings, empty when nothing is outstanding.

summary()

summary() : list<array{code: string, severity: int, rung: string, scopes: int, newest: int}>

Open findings collapsed to one row per code.

Returns

list

One entry per open code, worst severity first.

resolve()

resolve(string  $code, string  $scope) : int

Clears the findings for one code and scope.

Parameters

string $code

The finding code.

string $scope

The exact scope that has been dealt with.

Returns

int —

How many findings were cleared.

purge()

purge(int  $olderThan) : int

Drops findings recorded before a point in time.

Parameters

int $olderThan

Unix timestamp; findings recorded strictly before this are dropped.

Returns

int —

How many findings were dropped.

rungFor()

rungFor(string  $code) : string

The rung a code currently sits at.

With no rung set explicitly, the answer is derived from the worst severity recorded for the code, so a caller that has only ever recorded findings still gets a usable starting rung instead of having to seed one first. A code with nothing recorded sits at the bottom.

Parameters

string $code

The finding code.

Returns

string —

A rung name from RepairLadder::RUNGS.

setRung()

setRung(string  $code, string  $rung) : void

Moves a code to a rung.

An unknown rung is refused rather than stored, because RepairLadder ranks a name it does not know as UNRANKED and isAutomatic() then refuses it forever - a typo would quietly park the code where no repair ever runs.

Parameters

string $code

The finding code.

string $rung

A rung name from RepairLadder::RUNGS.

Returns

void —

settle()

settle(string  $code, array  $kept) : void

Writes back what is left of a code's findings, forgetting the code when nothing is.

The rung goes with the last finding. A code with nothing outstanding is one the caller has stopped tracking, which is the same thing RepairLadder::decay() signals with NULL at the bottom of the ladder.

Parameters

string $code

The finding code.

array $kept

The rows that survived, in order.

Returns

void —

now()

now() : int

Reads the injected clock.

Throws

\UnexpectedValueException

When the injected clock returns anything but an int, which would otherwise reach purge() as a comparison that quietly keeps or drops everything.

Returns

int —

A unix timestamp.