Docs: [CultIndex] is unique, [CultRole] names a selection role
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
46a40e774b
commit
a9b955660e
4 changed files with 22 additions and 13 deletions
|
|
@ -33,9 +33,9 @@ Recovered from the legacy "Database Tools" window (Aetheria `d3db1730`,
|
|||
**The attribute is not `[CultIndex]`.** `[CultIndex]` means unique (operator, 2026-09-30;
|
||||
`CultDocumentContracts.cs:34`). Grouping is `CultInspectorGroupByAttribute`, in
|
||||
`CultInspectorAttributes.cs`, read only by `CultInspectorModel`. It changes no schema id,
|
||||
catalog entry, index, or store byte. The index cut's deletion of grouping-only `[CultIndex]`
|
||||
declarations (CultMesh, Geometry) adds no `[CultInspectorGroupBy]` in their place: those are
|
||||
service stores, not Studio-authored catalogs.
|
||||
catalog entry, index, or store byte. The index cut converts the grouping and selection `[CultIndex]`
|
||||
declarations (CultMesh, Geometry) to `[CultRole]` rather than deleting them, and adds no
|
||||
`[CultInspectorGroupBy]` in their place: those are service stores, not Studio-authored catalogs.
|
||||
|
||||
### Invariants
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ which route wrote it.
|
|||
already agree when publication starts.
|
||||
- An admission runs a record's `[CultName]` and `[CultIndex]` getters once per
|
||||
landing record, before the store is written and before any `Sequence` is
|
||||
minted. A conditional commit on a clean file store is judged a second time
|
||||
minted. An admission is refused when it would leave two records of one type
|
||||
holding one `[CultIndex]` value (blank is no value), and a load of a store
|
||||
holding such a pair refuses naming both keys and the index. A conditional commit on a clean file store is judged a second time
|
||||
against the file it merges onto whenever the cache holds variants in any store,
|
||||
the batch lands a variant, or the file holds one. That second read runs the
|
||||
getters again for the records the batch lands, for any variant it re-resolves,
|
||||
|
|
|
|||
|
|
@ -22,9 +22,12 @@ public sealed class ItemData
|
|||
|
||||
[Key(1)]
|
||||
[CultIndex]
|
||||
public string Category = string.Empty;
|
||||
public string Sku = string.Empty;
|
||||
|
||||
[Key(2)]
|
||||
public string Category = string.Empty;
|
||||
|
||||
[Key(3)]
|
||||
public int Value;
|
||||
}
|
||||
```
|
||||
|
|
@ -33,7 +36,8 @@ Available cache attributes:
|
|||
|
||||
- `CultDocument(schemaName, schemaVersion)`
|
||||
- `CultName`
|
||||
- `CultIndex(alias?)`
|
||||
- `CultIndex(alias?)`: a unique lookup. Within one document type, a non-blank value names one record; a commit that would leave two records holding one is refused, and a store holding such a pair refuses to load.
|
||||
- `CultRole(alias?)`: a selection and reference role. Many records may share a value; it is never a lookup.
|
||||
- `CultGlobal`
|
||||
- `CultReference(targetType?, many: false)`
|
||||
|
||||
|
|
@ -53,6 +57,7 @@ var cache = new CultCache();
|
|||
var handle = await cache.AddAsync(new ItemData
|
||||
{
|
||||
Name = "Potion",
|
||||
Sku = "POT-1",
|
||||
Category = "Consumable",
|
||||
Value = 50
|
||||
});
|
||||
|
|
@ -66,7 +71,7 @@ Name and index lookups are driven from attributes, not manual registration.
|
|||
|
||||
```csharp
|
||||
var byName = cache.GetByName<ItemData>("Potion");
|
||||
var byIndex = cache.GetByIndex<ItemData>("Category", "Consumable");
|
||||
var byIndex = cache.GetByIndex<ItemData>("Sku", "POT-1");
|
||||
```
|
||||
|
||||
### Explicit references
|
||||
|
|
@ -130,6 +135,7 @@ var cache = await CultCacheMessagePack.OpenAsync("Data.msgpack");
|
|||
var handle = await cache.UpsertAsync(new ItemData
|
||||
{
|
||||
Name = "Potion",
|
||||
Sku = "POT-1",
|
||||
Category = "Consumable",
|
||||
Value = 50
|
||||
});
|
||||
|
|
|
|||
|
|
@ -321,15 +321,16 @@ var bySchema = documents.DocumentBySchema("gamecult.aetheria.station_refit.v1");
|
|||
Typed collections use the same one-call style:
|
||||
|
||||
```csharp
|
||||
var allies = CultMesh.CollectionByIndex<PlayerShipDocument>(
|
||||
// A [CultIndex] value is unique within its type, so the handle holds at most one record.
|
||||
var flagship = CultMesh.CollectionByIndex<PlayerShipDocument>(
|
||||
node,
|
||||
"Faction",
|
||||
"au");
|
||||
"CallSign",
|
||||
"au-1");
|
||||
|
||||
var currentAllies = await allies.LatestAsync();
|
||||
using var changes = allies.WatchChanges(change => UpdateRoster(change));
|
||||
var currentFlagship = await flagship.LatestAsync();
|
||||
using var changes = flagship.WatchChanges(change => UpdateRoster(change));
|
||||
|
||||
var collections = CultMesh.Collections(allies);
|
||||
var collections = CultMesh.Collections(flagship);
|
||||
var roster = await collections.LatestAsync<PlayerShipDocument>();
|
||||
using var rosterChanges = collections.WatchChanges<PlayerShipDocument>(RenderRoster);
|
||||
```
|
||||
|
|
|
|||
Loading…
Reference in a new issue