MICROSECONDS_PER_SECOND
MICROSECONDS_PER_SECOND = 1000000
Microseconds in a second, the unit $microtime is recorded in.
One captured mutation, and the only shape the journal appends.
A value object rather than an array, so a misspelled key is a type error at the call site instead of a silently absent field, and so the fields a restore depends on are checked once, here, rather than again in every writer that reads them.
An op describes a mutation and never carries the value. The value is in the object store under $payloadHash, which keeps a journal row the same size whether the subject is a taxonomy term or a 200 MiB file. $parentHash names the version the mutation was applied to, so a chain can be walked backwards without reading a payload at all.
$sequence orders every op in a window and is assigned by the journal on append, so a caller builds the op and gets its number back through withSequence().
$realm : \Drupal\strata\Journal\Realm
$verb : \Drupal\strata\Journal\Verb
__construct(int $sequence, int $microtime, \Drupal\strata\Journal\Realm $realm, string $subject, \Drupal\strata\Journal\Verb $verb, int|null $actor = null, string|null $requestId = null, string|null $payloadHash = null, string|null $parentHash = null, int $payloadLength = 0, string $label = '', list$fields = []) : mixed
Constructs an op.
| int | $sequence | Position in the window, assigned by the journal on append. Zero or more. |
| int | $microtime | Unix timestamp in microseconds, as |
| \Drupal\strata\Journal\Realm | $realm | The subsystem the subject lives in. |
| string | $subject | What was mutated, addressed the way its realm addresses things: |
| \Drupal\strata\Journal\Verb | $verb | What the mutation did. |
| int|null | $actor | Uid that caused the mutation, or NULL for cron, drush and anything else with no session. |
| string|null | $requestId | Identifier of the request the mutation happened in, so ops that belong to one page submission can be grouped after the fact. NULL when the writer did not record one. |
| string|null | $payloadHash | Digest of the value after the mutation, or NULL when there is no value to store, as for a delete. |
| string|null | $parentHash | Digest of the value before the mutation, or NULL when the subject had no previous version. |
| int | $payloadLength | Length of the value in bytes, so a window can be totalled without reading the store. |
| string | $label | Human-readable description for the UI, such as "Article: Hello world". |
| list |
$fields | Top-level field names the mutation touched. Empty when the writer does not track fields, or when the verb replaces the whole subject. |
When a number is out of range, the subject is empty, a hash is not a valid digest, $fields is not a list of names, or a string the op carries is not valid UTF-8.
timestamp() : float
When the mutation happened, as a float unix timestamp.
Microseconds are stored as an integer so ordering and equality are exact; this is the form for a formatter or a duration, not for a comparison.
Seconds since the epoch, with microsecond resolution.
withSequence(int $sequence) : self
The same op at a different position in the window.
The journal numbers an op on append, and the collapser renumbers nothing: a survivor keeps the sequence of the run it replaces.
| int | $sequence | The new sequence. Zero or more. |
When $sequence is negative.
A copy with the new sequence and every other field unchanged.
fromArray(array$data) : self
Rebuilds an op from its serialized form.
The five fields an op cannot be understood without are required; everything else defaults to the value the constructor defaults to, so a row written before a field existed still loads.
| array |
$data | The array produced by JournalOp::jsonSerialize(). |
When a required key is missing, or a value is out of range.
When the realm or the verb is not a case this version knows.
The op.
refuseUnrepresentable() : void
Refuses an op carrying a string that JSON cannot represent.
json_encode() returns FALSE when any string in the document is not valid UTF-8, and the
whole document goes with it - not the offending string. SegmentManifest is that document, so
one unrepresentable subject would take every operation in the flush with it. Refusing here
bounds the loss to the one op: every capture source catches, records a finding and returns,
and the reconciler notices the gap on its next pass.
The strings are checked as one newline-joined document because this runs on every captured
mutation, and which one failed is worked out only on the path that is about to throw. The
separator has to be there and has to be ASCII: joined bare, a subject ending in a truncated
"\xC3" and a label opening with "\xA9" form a valid two-byte sequence across the seam and both
halves pass, while json_encode() still refuses each of them on its own. An ASCII byte can
neither continue nor complete a multibyte sequence, so with one between them the joined check
is exactly the per-string check.
When the subject, the label or a field name is not valid UTF-8.
isRepresentable(string $value) : bool
Whether a string survives JSON.
//u fails to match when the subject is not valid UTF-8, which is the same condition
json_encode() refuses on. PCRE is always compiled in, where mbstring and iconv are core
requirements this module does not declare.
| string | $value | The string. |
TRUE when it is valid UTF-8.