An exemption cannot name the rows it covers, only the columns #151
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Exemptionmatches a table and its columns. It cannot say which rows, so anentry that covers two rows hides the column for all of them.
The case that raised it, from #110's library tile: the tile this server draws
agrees with upstream on path, type and 960×540, and its
Blurhashcannot agree,because upstream draws the library's name across the tile at 112 points in the
host's default typeface — so no two upstream installs agree either. Writing that
entry today means naming
Blurhashacross the whole ofBaseItemImageInfos,hiding the column for the ~120 fetched pictures whose hashes do agree in order
to cover two
CollectionFolderrows.No entry was opened. The reason went into
crates/jellyfin-harness/README.mdinstead, because no run has produced the difference: both snapshots already
carry upstream's tiles, and either server leaves a row that already has a picture
alone, so producing it takes a library neither side has drawn yet, scanned by
both. An entry for a difference no run has shown is the adds-only smell the risk
table names.
Where to start
A
rowspredicate onExemption— enough to name a row by the column valuesthat identify it, the way
masknames a field inside a blob. The two existingscoping mechanisms (
scope: "value"andmask) are the precedent for how narrowan entry is expected to be.
How to know it is done
The library-tile entry can be written honestly when a run produces the
difference:
Blurhashhidden onCollectionFolderrows and diffed on everyother row of the same table. Until then this is a harness feature with one
waiting customer, which is why it is filed rather than built.
House rules
Tests run under
cargo nextest.crates/jellyfin-harness/README.mdsays what adiff means and what an entry has to carry — every entry needs a reason and an
expiry, and an adds-only history is a smell.
Batch D produced no evidence for this, so it stays filed.
The batch's plan was that #150 might answer it — if ours sorted
Datakeyseverywhere, the difference would have been row-scoped and would have needed an
entry that could name rows. It does not: two writers took their top-level
object from
serde_json, and both are fixed rather than exempted (0afe805).The
AncestorIdshalf is a row one side files and the other does not, which anexemption could not cover anyway — it hides columns, not rows.
So the customer is still the library tile alone, and producing its difference
still takes a library neither side has drawn yet, scanned by both. An entry for
a difference no run has shown is the adds-only smell.
One thing worth writing down for whoever builds it: the motivating rows cannot
be named by a type.
BaseItemImageInfoscarriesItemId,Path,Blurhash,ImageTypeand the dimensions — nothing that saysCollectionFolder. Namingthe two library tiles inside that table means naming them by
Path, so arowspredicate that only compares column values for equality will not reachthem; it needs at least a prefix or glob. That is a constraint on the design,
not a reason to change the priority.
Landed in
f345ac6, with review fixes in611fa42."rows"narrows an exemption to the rows it is about, as{"column": "glob"}.GLOBrather than equality, because this issue's own comment recorded that themotivating rows cannot be named by value:
BaseItemImageInfoscarries no columnsaying
CollectionFolder, so the library tiles inside it have to be named by apath prefix. Every column given has to match.
scopekeeps its meaning within the rows named — a value-scoped entry over themstill reports a column one side wrote and the other left null — and a
field-scoped entry can no longer drop the column from the projection, because
the other rows are still being diffed, so it collapses the value on the rows it
names instead.
No entry uses it. The library tile is still the one waiting customer and its
difference still takes a library neither side has drawn yet, scanned by both. An
entry for a difference no run has shown is the adds-only smell.
Three ways the first cut could have widened an entry silently
All found by review, all fixed and each with a test that fails against the old
shape:
row predicate discarded, every column of every row hidden. Refused at load
now, as is a column two entries name, where only the first was ever read.
exemptandset.That is safe only while every row is substituted, and naming rows ends it: a
column upstream wrote a hash into and this server wrote
exemptinto read asagreeing. They are blobs now —
quoterenders a blob asX'…'and text as'…', so neither is a value either side can hold.sweep. Those are counted and named in the output, which is what the response
list's accounting already does for an entry nobody sees.
Two
GLOBbehaviours are written down beside the field, because both will bemet: it is case-sensitive, unlike the table and column names around it, and a
null in the column matches nothing —
{"Path": "*"}is every row that has apath. Both fail closed.