From f04e8fe7d75df2ff311ea9c05a24bb4b28dbf0c2 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 12 Jul 2026 21:48:28 +0100 Subject: [PATCH] Batch immutable reads through managed sessions --- src/GameCult.Mesh/CultMeshClient.cs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/GameCult.Mesh/CultMeshClient.cs b/src/GameCult.Mesh/CultMeshClient.cs index aeef39b3..bc6e604a 100644 --- a/src/GameCult.Mesh/CultMeshClient.cs +++ b/src/GameCult.Mesh/CultMeshClient.cs @@ -150,6 +150,24 @@ namespace GameCult.Mesh ThrowIfDisposed(); if (string.IsNullOrWhiteSpace(endpointId)) throw new ArgumentException("Endpoint identity is required.", nameof(endpointId)); if (string.IsNullOrWhiteSpace(recordKey)) throw new ArgumentException("Record key is required.", nameof(recordKey)); + var documents = await ReadManyAsync(endpointId, new[] { recordKey }, cancellationToken) + .ConfigureAwait(false); + return documents.FirstOrDefault() + ?? throw new InvalidOperationException( + $"CultMesh endpoint '{endpointId}' did not publish {typeof(TDocument).FullName} record '{recordKey}'."); + } + + /// Reads typed records once in one request through the reusable document session. + public async Task> ReadManyAsync( + string endpointId, + IReadOnlyList recordKeys, + CancellationToken cancellationToken = default) + where TDocument : class + { + ThrowIfDisposed(); + if (string.IsNullOrWhiteSpace(endpointId)) throw new ArgumentException("Endpoint identity is required.", nameof(endpointId)); + if (recordKeys == null || recordKeys.Count == 0 || recordKeys.Any(string.IsNullOrWhiteSpace)) + throw new ArgumentException("At least one non-empty record key is required.", nameof(recordKeys)); var cacheRegistry = CultMesh.CreateCultCacheDocumentRegistry(typeof(TDocument)); var networkRegistry = CultMesh.CreateCultNetDocumentRegistry(new[] { typeof(TDocument) }, cacheRegistry); using var snapshot = await CultMeshSnapshotSession.ConnectAsync( @@ -159,13 +177,10 @@ namespace GameCult.Mesh networkRegistry, cancellationToken) .ConfigureAwait(false); - var documents = await snapshot.FetchDocumentsAsync( - recordKeys: new[] { recordKey }, + return await snapshot.FetchDocumentsAsync( + recordKeys: recordKeys, schemaIds: new[] { cacheRegistry.GetRequired().SchemaId }) .ConfigureAwait(false); - return documents.FirstOrDefault() - ?? throw new InvalidOperationException( - $"CultMesh endpoint '{endpointId}' did not publish {typeof(TDocument).FullName} record '{recordKey}'."); } public void Dispose()