\Drupal\strata\Capture StateCapture

Records state writes by wrapping the state service.

State has no events, and it is not a factory, so decoration is the way in. Every read passes straight through; every write is journaled and then delegated.

The old value is read before a write, because the decorator has no other way to tell a create from an update and because a restore of a create has to know the key did not exist. State handles ~580 operations a day on a 50,000-user site - under 1% of write volume - so one extra read per write is not a cost worth optimising away, and getMultiple() makes the batch case one query rather than N.

The whole value is stored rather than a delta. State values are small and structurally arbitrary, so a field-level diff would cost more to compute and store than the value itself.

Both contracts have to be satisfied, not just StateInterface. Core's State extends CacheCollector, and core calls the collector's own methods on the service by name: the test runner's RefreshVariablesTrait calls reset() on state with no is_callable guard at all. A decorator declaring only StateInterface therefore compiles, installs, serves pages, and then fails the moment anything reaches for the half of the surface the interface does not describe.

Summary

Methods
Properties
Constants
__construct
get
getMultiple
resetCache
getValuesSetDuringRequest
has
reset
clear
set
setMultiple
delete
deleteMultiple
destruct
No public properties found
No public constants found
No protected methods found
No protected properties found
No protected constants found
exists
inner
recorder
No private constants found

Properties

$inner

$inner : \Drupal\Core\State\StateInterface

Type

StateInterface

$recorder

$recorder : \Drupal\strata\Capture\KeyRecorder

Type

KeyRecorder

Methods

__construct()

__construct(\Drupal\Core\State\StateInterface  $inner, \Drupal\strata\Capture\KeyRecorder  $recorder) : mixed

Constructs the decorator.

Parameters

\Drupal\Core\State\StateInterface $inner

The state service being wrapped.

\Drupal\strata\Capture\KeyRecorder $recorder

Journals each write.

Returns

mixed —

get()

get(mixed  $key, mixed  $default = null) : mixed

{@inheritdoc}

Parameters

mixed $key
mixed $default

Returns

mixed —

getMultiple()

getMultiple(array  $keys) : mixed

{@inheritdoc}

Parameters

array $keys

Returns

mixed —

resetCache()

resetCache() : mixed

{@inheritdoc}

Returns

mixed —

getValuesSetDuringRequest()

getValuesSetDuringRequest(string  $key) : ?array

{@inheritdoc}

Parameters

string $key

Returns

?array —

has()

has(mixed  $key) : mixed

{@inheritdoc}

Part of the collector contract rather than the state one, and answered from the inner service so a key written this request counts as present.

Parameters

mixed $key

Returns

mixed —

reset()

reset() : mixed

{@inheritdoc}

Nothing is journaled: discarding a local cache changes no stored value. An inner service that is not a collector has no cache to discard, which is why this is a no-op rather than a throw.

Returns

mixed —

clear()

clear() : mixed

{@inheritdoc}

Also not journaled. clear() empties the collector's cache bin rather than the state values themselves, so nothing a restore would put back has changed.

Returns

mixed —

set()

set(mixed  $key, mixed  $value) : mixed

{@inheritdoc}

Parameters

mixed $key
mixed $value

Returns

mixed —

setMultiple()

setMultiple(array  $data) : mixed

{@inheritdoc}

Parameters

array $data

Returns

mixed —

delete()

delete(mixed  $key) : mixed

{@inheritdoc}

Parameters

mixed $key

Returns

mixed —

deleteMultiple()

deleteMultiple(array  $keys) : mixed

{@inheritdoc}

Parameters

array $keys

Returns

mixed —

destruct()

destruct() : void

{@inheritdoc}

State is a cache collector, and the needs_destruction tag on the service is what makes it write its collected values out at the end of a request. Decorating the service moves that tag to this class, so a decorator that did not pass the call through would silently stop state being persisted at all - a failure that looks like nothing until a value goes missing.

Returns

void —

exists()

exists(string  $key) : bool

Whether a key currently holds a value.

A sentinel is used rather than comparing against NULL, since NULL is a value state can hold and a restore that turned a stored NULL into a missing key would be wrong.

Parameters

string $key

The state key.

Returns

bool —

TRUE when the key is set.