PARTIAL
PARTIAL = 'restore.partial'
Code raised when a restore would not be able to put everything back.
Works out what a restore can and cannot put back, before it writes anything.
Every subject in scope is replayed and classified. That is deliberately expensive: it reads the same objects the apply will read, so a plan that says restorable has proved it rather than assumed it, and an operator confirming a rollback is looking at a measurement.
The default for a degraded subject is to leave it alone. A partial field set written over a live value produces a record that is neither the old one nor the new one, in a system whose whole purpose is to be trusted about what the site used to look like. Filling the gaps with defaults is available per scope and is spelled out subject by subject before it happens.
Anything the preflight could not classify raises restore.partial, so a restore that was never
run still leaves evidence of why.
$replayer : \Drupal\strata\Restore\Replayer
$commits : \Drupal\strata\Tree\CommitLog
$ledger : \Drupal\strata\Health\HealthLedgerInterface
$subjects : ?\Drupal\strata\Tree\SubjectIndex
__construct(\Drupal\strata\Restore\Replayer $replayer, \Drupal\strata\Tree\CommitLog $commits, \Drupal\strata\Health\HealthLedgerInterface $ledger, \Drupal\strata\Tree\SubjectIndex|null $subjects = null) : mixed
Constructs a preflight.
| \Drupal\strata\Restore\Replayer | $replayer | Reconstructs each subject. |
| \Drupal\strata\Tree\CommitLog | $commits | Resolves the target and reports the replay depth. |
| \Drupal\strata\Health\HealthLedgerInterface | $ledger | Where a partial plan is recorded. |
| \Drupal\strata\Tree\SubjectIndex|null | $subjects | Consulted for when each subject was last written, which is what makes a conflict detectable. NULL plans without conflict detection, which is what a store with no local index can do. |
plan(string $target, bool $fillDegraded = false, int|null $limit = null, bool $acceptConflicts = false) : \Drupal\strata\Restore\RestorePlan
Plans a restore of every subject a commit covers.
| string | $target | Commit id to restore to. |
| bool | $fillDegraded | TRUE to write partial reconstructions as well. Off unless a human asked. |
| int|null | $limit | Most subjects to plan, or NULL for all of them. |
| bool | $acceptConflicts | TRUE to write a subject somebody changed while the plan was waiting. Off unless a human asked. |
The plan.
planSubjects(string $target, list$subjects, bool $fillDegraded = false, bool $acceptConflicts = false) : \Drupal\strata\Restore\RestorePlan
Plans a restore of named subjects only.
The surgical case: one node, one config object, one table row. A subject the target does not cover is planned anyway and comes back unrestorable, because "that node did not exist then" is an answer an operator needs rather than an error.
| string | $target | Commit id to restore to. |
| list |
$subjects | Subject paths, such as "entity/node:42". |
| bool | $fillDegraded | TRUE to write partial reconstructions as well. |
| bool | $acceptConflicts | TRUE to write a subject somebody changed while the plan was waiting. Off unless a human asked. |
The plan.
concurrentChanges(\Drupal\strata\Restore\RestorePlan $plan) : array<string,\Drupal\strata\Restore\Conflict>
The subjects a plan covers that somebody has changed since it was built.
Called at apply time rather than at plan time, because at plan time nothing can have changed yet. A plan applied straight away finds nothing here; one that waited for a second approval may find several, and those are the writes nobody reviewing the plan saw.
Read from the local subject index, which records when each subject was last written, so this is one query and no object reads. A store with no local index detects nothing and says so by returning an empty set rather than by claiming there are none.
| \Drupal\strata\Restore\RestorePlan | $plan | The plan being applied. |
Subject path keyed to the conflict, empty when the plan carries no build time to compare against.
isRestorableRealm(string $subject) : bool
Whether a restore writes subjects in a path's realm back at all.
Ephemeral state is captured so a restore can report what it invalidated, and never written back: the restored data rebuilds it, and writing a stale cache entry over a live bin costs more than the rebuild.
| string | $subject | Subject path. |
TRUE when the realm is restorable, and for a path whose realm is not one this release knows, since a subject from a newer capture is not something to silently drop.
planFor(string $target, list$subjects, bool $fillDegraded, list $problems, float $started, bool $acceptConflicts = false) : \Drupal\strata\Restore\RestorePlan
Builds the plan for a resolved subject list.
| string | $target | Commit id. |
| list |
$subjects | Subject paths. |
| bool | $fillDegraded | Whether partial reconstructions are written. |
| list |
$problems | Problems collected so far. |
| float | $started | When planning began. |
| bool | $acceptConflicts | Whether subjects changed since the restore point are written anyway. |
The plan.