Caching: PersistedSchemaId and MarkWritten are internal for 2.0; Mesh single-file write guard in the CHANGELOG

C2a's StoredVersion owns the same identity and deletes both. No consumer outside CultLib uses them,
so they do not ship public in 2.0.0 and C2a's release is not a major.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-22 15:57:01 +02:00
commit 8b47a2e8d9
4 changed files with 13 additions and 17 deletions

View file

@ -227,13 +227,14 @@ against what is durably on disk at that moment:
`(key, schemaId, storedAt)`. Any insert, delete or replace fails it.
Record identity for conditions is `(schemaId, storedAt)`, where `schemaId` is
the id the record is persisted under (`CultStoredDocument.PersistedSchemaId`),
the id the record is persisted under (the internal `CultStoredDocument.PersistedSchemaId`),
not the one this cache decodes it as. A value change mints a `storedAt`
strictly later than the record it replaces; writers bump a minted timestamp by
one tick when it is not later. An entry loaded under compatible schema drift
keeps its persisted id until its store rewrites it; a store records each
record its completed write rewrote with the protected instance method
`CacheBackingStore.MarkWritten`, which refuses an entry that is not the one
record its completed write rewrote with the internal instance method
`CacheBackingStore.MarkWritten` (the shipped stores call it; it is not part of
the public API), which refuses an entry that is not the one
the store holds in its own `Entries` at that key. That guards against a store
marking by mistake an entry it never held; a store that writes another copy
into its own `Entries` and then marks it is trusted to have rewritten that

View file

@ -394,9 +394,9 @@ namespace GameCult.Caching
/// The schema id this record is durably stored under, as its backing store last read or wrote it. It differs from
/// <see cref="CultDocumentDescriptor.SchemaId"/> only for a record loaded under compatible schema drift that its
/// store has not rewritten since; a store records its rewrite of an entry it holds with <see cref="CacheBackingStore.MarkWritten"/>.
/// Conditional commit compares this id and <see cref="StoredAt"/> with the disk.
/// Conditional commit compares this id and <see cref="StoredAt"/> with the disk. Internal to the shipped stores.
/// </summary>
public string PersistedSchemaId => _persisted.SchemaId;
internal string PersistedSchemaId => _persisted.SchemaId;
// The complete document. For a variant, the resolved view: derived, never written back.
public object Document => _document ??
@ -3333,7 +3333,7 @@ namespace GameCult.Caching
/// </summary>
/// <exception cref="ArgumentException"><paramref name="entry"/> is not the entry this store holds in
/// <see cref="Entries"/> at its key: a store marks only its own rewrite.</exception>
protected void MarkWritten(CultStoredDocument entry)
internal void MarkWritten(CultStoredDocument entry)
{
if (entry == null)
throw new ArgumentNullException(nameof(entry));

View file

@ -9,5 +9,6 @@
<PackageReference Include="R3" Version="1.3.0" />
<PackageReference Include="ConcurrentHashSet " Version="1.3.0" />
<InternalsVisibleTo Include="GameCult.Caching.Tests" />
<InternalsVisibleTo Include="GameCult.Caching.MessagePack" />
</ItemGroup>
</Project>

View file

@ -76,20 +76,14 @@ All notable changes to this package are documented in this file.
reading it. A store with no variant stays `cultcache.store.v1`, byte-identical to
1.0.x. CultMesh single-file reads, the directory store and CultNet refuse a variant
record by name; only the C# CultCache resolves variants.
- `CultMesh.WriteSingleFileDocument` and `WriteSingleFileDocumentPayload` read the
file they replace, under the store's `<path>.lock`, and refuse (without touching
it) a file this runtime cannot read, a store stamped with a newer format version,
or one holding any record besides the key being written. They used to replace the
file whole. Write to a store that holds several records through a `CultCache`.
### Added
- `CultStoredDocument.PersistedSchemaId`: the schema id a record is durably
stored under, as its backing store last read or wrote it. It differs from
`Descriptor.SchemaId` only for a record loaded under compatible schema drift
that its store has not rewritten since.
- `CacheBackingStore.MarkWritten(CultStoredDocument)` (protected instance
method): a backing store records that its completed durable write stored a
record under its descriptor, so `PersistedSchemaId` follows the rewrite. It
throws `ArgumentException` for an entry that is not the one the store holds
in its own `Entries`. The single-file and directory stores mark every record
they rewrite; a custom store calls it for each record its own write rewrote.
- Variants: a record that stores only its difference from a base record, resolved in
memory when the cache admits it (`cultcache.store.v2`; see the persistence-format
contract). A plain write at a variant's key is refused, and `Flatten` replaces a