TOO_DEEP
TOO_DEEP = 'delta.chain_too_deep'
Code raised when a chain is found past the cap.
Breaks delta chains that have grown too long by rewriting a link standalone.
Delta coding trades storage for a dependency. A frame coded against the version before it is 63.70x smaller on the rewrite class, and reading it reads its parent, and that parent's parent. The chain is what makes the saving and it is also the whole risk: a long chain multiplies read cost and turns one lost frame into the loss of everything derived from it.
So a chain is capped, and this is what enforces the cap after the fact. The writer refuses to extend a chain past the limit, which keeps new frames in bounds; a chain can still be over the limit because the limit was lowered, or because a chain was built by an older release. Rewriting the deepest link standalone cuts the chain there: everything above it keeps its parent, everything below it becomes reachable in fewer reads.
Nothing is deleted. The rewritten frame keeps its content address, because the address is the digest of the decoded bytes and those are unchanged - only the encoding changes. Every frame that named it still names it, and the old bytes are superseded rather than orphaned.
DEFAULT_BUDGET = 200
Frames rewritten in one pass by default.
Each one is a read of its whole chain and a write, so a pass is bounded and the next cron run continues. A cap that let one pass rewrite an unbounded number of frames would be the slowest thing in the cron queue on the one site that needed it most.
$index : \Drupal\strata\Cas\FrameIndexInterface
$store : \Drupal\strata\Cas\ObjectStore
$policy : \Drupal\strata\Delta\ChainDepthPolicy
$ledger : \Drupal\strata\Health\HealthLedgerInterface
__construct(\Drupal\strata\Cas\FrameIndexInterface $index, \Drupal\strata\Cas\ObjectStore $store, \Drupal\strata\Delta\ChainDepthPolicy $policy, \Drupal\strata\Health\HealthLedgerInterface $ledger, \Psr\Log\LoggerInterface $logger) : mixed
Constructs a reanchorer.
| \Drupal\strata\Cas\FrameIndexInterface | $index | Where chain depths are read from and written back. |
| \Drupal\strata\Cas\ObjectStore | $store | Reads a frame through its chain and writes the standalone replacement. |
| \Drupal\strata\Delta\ChainDepthPolicy | $policy | The cap being enforced. |
| \Drupal\strata\Health\HealthLedgerInterface | $ledger | Where a chain past the cap is recorded. |
| \Psr\Log\LoggerInterface | $logger | Records what a pass did. |
run(int $budget = 0) : array{examined: int, reanchored: int, deepest: int, saved: int, problems: list<string>}
Rewrites the frames whose chains are past the cap.
| int | $budget | Most frames to rewrite, or zero for the default. |
How many frames were looked at, how many were rewritten, the deepest chain found, how many stored bytes the rewrites cost or saved, and anything that could not be done.
reanchor(\Drupal\strata\Cas\FrameRecord $record) : int
Rewrites one frame so it no longer depends on a parent.
| \Drupal\strata\Cas\FrameRecord | $record | The frame to re-anchor. |
When the frame cannot be read through its chain, or the rewrite cannot be stored.
Stored bytes saved, which is negative when the standalone form is larger - and it usually is. The point of a re-anchor is bounding the read, not saving bytes, and reporting the cost honestly is what lets an operator judge the cap.