Add C# configured publication document handles
This commit is contained in:
parent
47941b5fb3
commit
bcf877d87d
3 changed files with 161 additions and 11 deletions
|
|
@ -161,6 +161,105 @@ namespace GameCult.Mesh
|
|||
public CultDocumentRegistry? Registry { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes where a typed document publication should be read from.
|
||||
/// </summary>
|
||||
public abstract class CultMeshDocumentPublicationSource
|
||||
{
|
||||
private CultMeshDocumentPublicationSource()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Creates a publication source from a CultCache backing store.</summary>
|
||||
public static CultMeshDocumentPublicationSource Store(CacheBackingStore store)
|
||||
{
|
||||
return new StoreSource(store);
|
||||
}
|
||||
|
||||
/// <summary>Creates a publication source from a single-file MessagePack CultCache publication.</summary>
|
||||
public static CultMeshDocumentPublicationSource SingleFile(string path)
|
||||
{
|
||||
return new SingleFileSource(path);
|
||||
}
|
||||
|
||||
/// <summary>Creates a publication source from a remote CultNet snapshot response provider.</summary>
|
||||
public static CultMeshDocumentPublicationSource PeerSnapshot(Func<CultMeshQueryContext, Task<CultNetSnapshotResponseRawMessage>> snapshot)
|
||||
{
|
||||
return new PeerSnapshotSource(snapshot);
|
||||
}
|
||||
|
||||
/// <summary>Creates a publication source from a remote CultNet schema endpoint.</summary>
|
||||
public static CultMeshDocumentPublicationSource PeerSnapshot(string endpoint)
|
||||
{
|
||||
return new PeerSnapshotEndpointSource(endpoint);
|
||||
}
|
||||
|
||||
/// <summary>Creates a publication source from a remote CultNet schema client factory.</summary>
|
||||
public static CultMeshDocumentPublicationSource PeerSnapshot(Func<ICultNetSchemaClient> createClient, string endpoint)
|
||||
{
|
||||
return new PeerSnapshotClientSource(createClient, endpoint);
|
||||
}
|
||||
|
||||
internal sealed class StoreSource : CultMeshDocumentPublicationSource
|
||||
{
|
||||
public StoreSource(CacheBackingStore store)
|
||||
{
|
||||
BackingStore = store ?? throw new ArgumentNullException(nameof(store));
|
||||
}
|
||||
|
||||
public CacheBackingStore BackingStore { get; }
|
||||
}
|
||||
|
||||
internal sealed class SingleFileSource : CultMeshDocumentPublicationSource
|
||||
{
|
||||
public SingleFileSource(string path)
|
||||
{
|
||||
Path = string.IsNullOrWhiteSpace(path)
|
||||
? throw new ArgumentException("Value must be non-empty.", nameof(path))
|
||||
: path;
|
||||
}
|
||||
|
||||
public string Path { get; }
|
||||
}
|
||||
|
||||
internal sealed class PeerSnapshotSource : CultMeshDocumentPublicationSource
|
||||
{
|
||||
public PeerSnapshotSource(Func<CultMeshQueryContext, Task<CultNetSnapshotResponseRawMessage>> snapshot)
|
||||
{
|
||||
Snapshot = snapshot ?? throw new ArgumentNullException(nameof(snapshot));
|
||||
}
|
||||
|
||||
public Func<CultMeshQueryContext, Task<CultNetSnapshotResponseRawMessage>> Snapshot { get; }
|
||||
}
|
||||
|
||||
internal sealed class PeerSnapshotEndpointSource : CultMeshDocumentPublicationSource
|
||||
{
|
||||
public PeerSnapshotEndpointSource(string endpoint)
|
||||
{
|
||||
Endpoint = string.IsNullOrWhiteSpace(endpoint)
|
||||
? throw new ArgumentException("Value must be non-empty.", nameof(endpoint))
|
||||
: endpoint;
|
||||
}
|
||||
|
||||
public string Endpoint { get; }
|
||||
}
|
||||
|
||||
internal sealed class PeerSnapshotClientSource : CultMeshDocumentPublicationSource
|
||||
{
|
||||
public PeerSnapshotClientSource(Func<ICultNetSchemaClient> createClient, string endpoint)
|
||||
{
|
||||
CreateClient = createClient ?? throw new ArgumentNullException(nameof(createClient));
|
||||
Endpoint = string.IsNullOrWhiteSpace(endpoint)
|
||||
? throw new ArgumentException("Value must be non-empty.", nameof(endpoint))
|
||||
: endpoint;
|
||||
}
|
||||
|
||||
public Func<ICultNetSchemaClient> CreateClient { get; }
|
||||
|
||||
public string Endpoint { get; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A locally hosted CultMesh node over CultCache, CultNet transport, and the mesh database facade.
|
||||
/// </summary>
|
||||
|
|
@ -1265,6 +1364,53 @@ namespace GameCult.Mesh
|
|||
return DocumentFromSingleFile<TDocument>(path, key, verse.Context, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a typed document handle from a configured publication source.
|
||||
/// </summary>
|
||||
public static CultMeshDocumentHandle<TDocument> DocumentFromPublication<TDocument>(
|
||||
CultMeshDocumentPublicationSource source,
|
||||
CultRecordKey key,
|
||||
CultMeshVerseContext context,
|
||||
CultMeshStoreDocumentOptions? storeOptions = null,
|
||||
CultMeshPeerSnapshotDocumentOptions? peerOptions = null)
|
||||
where TDocument : class
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException(nameof(source));
|
||||
if (context == null) throw new ArgumentNullException(nameof(context));
|
||||
|
||||
switch (source)
|
||||
{
|
||||
case CultMeshDocumentPublicationSource.StoreSource store:
|
||||
return DocumentFromStore<TDocument>(store.BackingStore, key, context, storeOptions);
|
||||
case CultMeshDocumentPublicationSource.SingleFileSource file:
|
||||
return DocumentFromSingleFile<TDocument>(file.Path, key, context, storeOptions);
|
||||
case CultMeshDocumentPublicationSource.PeerSnapshotSource snapshot:
|
||||
return DocumentFromPeerSnapshot<TDocument>(snapshot.Snapshot, key.Value, context, peerOptions);
|
||||
case CultMeshDocumentPublicationSource.PeerSnapshotEndpointSource endpoint:
|
||||
return DocumentFromPeerSnapshot<TDocument>(endpoint.Endpoint, key.Value, context, peerOptions);
|
||||
case CultMeshDocumentPublicationSource.PeerSnapshotClientSource client:
|
||||
return DocumentFromPeerSnapshot<TDocument>(client.CreateClient, client.Endpoint, key.Value, context, peerOptions);
|
||||
default:
|
||||
throw new NotSupportedException(
|
||||
$"Unsupported CultMesh document publication source '{source.GetType().FullName}'.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a typed document handle from a configured publication source.
|
||||
/// </summary>
|
||||
public static CultMeshDocumentHandle<TDocument> DocumentFromPublication<TDocument>(
|
||||
CultMeshDocumentPublicationSource source,
|
||||
CultRecordKey key,
|
||||
CultMeshVerse verse,
|
||||
CultMeshStoreDocumentOptions? storeOptions = null,
|
||||
CultMeshPeerSnapshotDocumentOptions? peerOptions = null)
|
||||
where TDocument : class
|
||||
{
|
||||
if (verse == null) throw new ArgumentNullException(nameof(verse));
|
||||
return DocumentFromPublication<TDocument>(source, key, verse.Context, storeOptions, peerOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a typed document handle directly over one distributed CultNet database record.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -182,6 +182,9 @@ var latestHealth = await health.LatestAsync();
|
|||
`DocumentFromStore<T>()` accepts any `CacheBackingStore`; both helpers pull,
|
||||
decode, resolve persisted schema metadata, and poll for updates behind the
|
||||
`CultMeshDocumentHandle<T>` surface.
|
||||
Use `DocumentFromPublication<T>()` when the caller should provide a configured
|
||||
source instead of branching between local files, backing stores, and remote
|
||||
CultNet snapshots itself.
|
||||
|
||||
## Game Session
|
||||
|
||||
|
|
|
|||
|
|
@ -872,8 +872,8 @@ public sealed class CultMeshStreamingTests
|
|||
await directReadCache.PullAllBackingStoresAsync();
|
||||
directReadCache.Get<MeshPublicationNoteDocument>(key)!.Text.Should().Be("published");
|
||||
|
||||
var handle = CultMesh.DocumentFromSingleFile<MeshPublicationNoteDocument>(
|
||||
filePath,
|
||||
var handle = CultMesh.DocumentFromPublication<MeshPublicationNoteDocument>(
|
||||
CultMeshDocumentPublicationSource.SingleFile(filePath),
|
||||
key,
|
||||
CultMesh.Verse("starbridge", "unity-pilot"),
|
||||
new CultMeshStoreDocumentOptions
|
||||
|
|
@ -921,16 +921,17 @@ public sealed class CultMeshStreamingTests
|
|||
.Register(CultNetDocumentBinding.ForDocument<MeshNoteDocument>(CultDocumentRegistry.Shared));
|
||||
var requests = new List<CultNetSnapshotRequestMessage>();
|
||||
|
||||
var handle = CultMesh.DocumentFromPeerSnapshot<MeshNoteDocument>(
|
||||
() => new MeshSnapshotSchemaClient(request =>
|
||||
{
|
||||
requests.Add(request);
|
||||
return registry.CreateRawSnapshotResponse(cache, request.MessageId, request);
|
||||
}),
|
||||
"cultnet://snapshot.test:3075",
|
||||
key.Value,
|
||||
var handle = CultMesh.DocumentFromPublication<MeshNoteDocument>(
|
||||
CultMeshDocumentPublicationSource.PeerSnapshot(
|
||||
() => new MeshSnapshotSchemaClient(request =>
|
||||
{
|
||||
requests.Add(request);
|
||||
return registry.CreateRawSnapshotResponse(cache, request.MessageId, request);
|
||||
}),
|
||||
"cultnet://snapshot.test:3075"),
|
||||
key,
|
||||
CultMesh.Verse("starbridge", "unity-pilot"),
|
||||
new CultMeshPeerSnapshotDocumentOptions
|
||||
peerOptions: new CultMeshPeerSnapshotDocumentOptions
|
||||
{
|
||||
PollInterval = TimeSpan.FromMilliseconds(10),
|
||||
MessageIdPrefix = "mesh-test-snapshot"
|
||||
|
|
|
|||
Loading…
Reference in a new issue