Caching: README section on element ids; the hex refusal names the derived form for readable ids
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0e964f45ac
commit
e3f497197d
3 changed files with 33 additions and 1 deletions
|
|
@ -290,7 +290,7 @@ namespace GameCult.Caching
|
|||
continue;
|
||||
if (shape.Derive == null && !IsRandomId(id!))
|
||||
throw new CultElementIdException(
|
||||
$"Record {rootPath}: element id '{id}' in the list at {path} is not 12 lowercase hex characters.",
|
||||
$"Record {rootPath}: element id '{id}' in the list at {path} is not 12 lowercase hex characters. An id you write by hand must be 12 lowercase hex; for readable ids, derive them from a member with [CultElementId(nameof(Member))].",
|
||||
rootPath, path, id);
|
||||
if (!taken.Add(id!))
|
||||
throw Duplicate(id!, path);
|
||||
|
|
|
|||
|
|
@ -188,6 +188,31 @@ for (var row = 0; row < table.Count; row++)
|
|||
cache-owned physical table for hot loops and diagnostics; it is not a second
|
||||
domain model callers have to maintain.
|
||||
|
||||
## Element ids
|
||||
|
||||
A document type that holds a list of objects gives every object type in that list
|
||||
(union arms included) a string member marked `[CultElementId]`, next to its
|
||||
`[Key]`. The id is what lets a variant override one list element instead of the
|
||||
whole list. Lists of strings, numbers and other non-object values need none.
|
||||
|
||||
```csharp
|
||||
[MessagePackObject]
|
||||
public sealed class Line
|
||||
{
|
||||
[Key(0)] [CultElementId] public string Id = string.Empty;
|
||||
[Key(1)] public string Text = string.Empty;
|
||||
}
|
||||
```
|
||||
|
||||
Leave `Id` empty and the cache mints a random id when the record is written. An
|
||||
id you set yourself must be exactly 12 lowercase hex characters
|
||||
(`0123456789ab`); anything else is refused with a `CultElementIdException`.
|
||||
|
||||
For readable ids, derive them: `[CultElementId(nameof(Name))]` makes an unset id
|
||||
the text of that member (a string or number on the same type, unique within its
|
||||
list), and a derived id may be any text. A readable name set by hand on a
|
||||
non-derived list id is refused; the same member outside a list is unconstrained.
|
||||
|
||||
## Persistence discipline
|
||||
|
||||
Persistence stays manual by default. Mutations mark the cache and attached
|
||||
|
|
|
|||
|
|
@ -135,6 +135,13 @@ namespace GameCult.Caching.Tests
|
|||
Assert.Throws<CultElementIdException>(() => Assign(grid, "r", deterministic: false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TheHexRefusalNamesTheDerivedFormForReadableIds()
|
||||
{
|
||||
var refusal = Assert.Throws<CultElementIdException>(() => Assign(new HHasIds { Items = { new EIded { Id = "root" } } }, "r", deterministic: false))!;
|
||||
Assert.That(refusal.Message, Does.Contain("12 lowercase hex").And.Contain("[CultElementId(nameof(Member))]"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ARandomIdMustBeTwelveLowercaseHexCharactersAndADerivedIdNeedOnlyBeText()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue