Route SoA latest view through managed state
This commit is contained in:
parent
9d623a24c6
commit
783ea271cc
8 changed files with 69 additions and 62 deletions
|
|
@ -83,25 +83,31 @@ static async Task ExportFixtureSetAsync(
|
|||
if (commands.Count > 0)
|
||||
WriteArtifact(outputDirectory, manifest, "commands.seeded", AetheriaRuntimeDaemonSchemas.Command + "[]", commands);
|
||||
|
||||
var frame = AetheriaRuntimeDaemonFrameStore.ReadFrame(statePath);
|
||||
await using var node = await AetheriaStateNode
|
||||
.OpenAsync(statePath, runtimeId: "aetheria-freeze", startServer: false)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var frame = await node.LatestFrame().ReadAsync().ConfigureAwait(false);
|
||||
if (frame == null)
|
||||
throw new InvalidOperationException("Freeze export cannot continue because the daemon latest frame is missing.");
|
||||
WriteArtifact(outputDirectory, manifest, "daemon-frame.latest", AetheriaRuntimeDaemonSchemas.Frame, frame);
|
||||
|
||||
if (AetheriaRuntimeDaemonPublicationStore.TryReadHealth(statePath, out var health))
|
||||
if (await TryReadAsync<AetheriaRuntimeDaemonHealthDocument>(() => node.Health().ReadAsync()).ConfigureAwait(false) is { } health)
|
||||
WriteArtifact(outputDirectory, manifest, "daemon-health.latest", AetheriaRuntimeDaemonSchemas.Health, health);
|
||||
|
||||
if (AetheriaRuntimeDaemonPublicationStore.TryReadProviderAdvertisement(statePath, out var provider))
|
||||
if (await TryReadAsync<AetheriaRuntimeDaemonProviderAdvertisementDocument>(() => node.ProviderAdvertisement().ReadAsync()).ConfigureAwait(false) is { } provider)
|
||||
WriteArtifact(outputDirectory, manifest, "daemon-provider.latest", AetheriaRuntimeDaemonSchemas.ProviderAdvertisement, provider);
|
||||
|
||||
if (AetheriaRuntimeDaemonPublicationStore.TryReadCommandBoundary(statePath, out var commandBoundary))
|
||||
if (await TryReadAsync<AetheriaRuntimeDaemonCommandBoundaryDocument>(() => node.CommandBoundary().ReadAsync()).ConfigureAwait(false) is { } commandBoundary)
|
||||
WriteArtifact(outputDirectory, manifest, "daemon-command-boundary.latest", AetheriaRuntimeDaemonSchemas.CommandBoundary, commandBoundary);
|
||||
|
||||
if (AetheriaRuntimeDaemonPublicationStore.TryReadVerseAuthorityPolicy(statePath, out var authorityPolicy))
|
||||
if (await TryReadAsync<AetheriaRuntimeVerseAuthorityPolicyDocument>(() => node.VerseAuthorityPolicy().ReadAsync()).ConfigureAwait(false) is { } authorityPolicy)
|
||||
WriteArtifact(outputDirectory, manifest, "verse-authority-policy.latest", AetheriaRuntimeVerseAuthoritySchemas.Policy, authorityPolicy);
|
||||
|
||||
if (AetheriaRuntimeDaemonPublicationStore.TryReadStarbridgeSessionSummary(statePath, out var starbridgeSummary))
|
||||
if (await TryReadAsync<AetheriaRuntimeStarbridgeSessionSummaryDocument>(() => node.StarbridgeSessionSummary().ReadAsync()).ConfigureAwait(false) is { } starbridgeSummary)
|
||||
WriteArtifact(outputDirectory, manifest, "starbridge-session-summary.latest", AetheriaRuntimeDaemonSchemas.StarbridgeSessionSummary, starbridgeSummary);
|
||||
|
||||
if (AetheriaRuntimeDaemonSoaViewStore.TryReadView(statePath, out var soaView))
|
||||
if (await TryReadAsync<AetheriaRuntimeDaemonSoaViewDocument>(() => node.LatestSoaView().ReadAsync()).ConfigureAwait(false) is { } soaView)
|
||||
WriteArtifact(outputDirectory, manifest, "daemon-soa-view.latest", AetheriaRuntimeDaemonSchemas.SoaView, soaView);
|
||||
|
||||
var viewport = new AetheriaRuntimeRtsViewportBounds
|
||||
|
|
@ -142,6 +148,19 @@ static void ExportAuthorityDecisionFixtures(string outputDirectory)
|
|||
WriteJson(Path.Combine(outputDirectory, "manifest.json"), manifest);
|
||||
}
|
||||
|
||||
static async Task<T?> TryReadAsync<T>(Func<Task<T?>> read)
|
||||
where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
return await read().ConfigureAwait(false);
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static void ExportYmirQueryFixtures(string outputDirectory)
|
||||
{
|
||||
Directory.CreateDirectory(outputDirectory);
|
||||
|
|
|
|||
|
|
@ -8675,7 +8675,6 @@ static void RequireDaemonVersePublication(string root)
|
|||
var daemonFrameStorePath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonFrameStore.cs");
|
||||
var daemonPublicationStorePath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonPublicationStore.cs");
|
||||
var daemonSoaDocumentsPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonSoaDocuments.cs");
|
||||
var daemonSoaViewStorePath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonSoaViewStore.cs");
|
||||
var daemonSoaFramePublisherPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonSoaFramePublisher.cs");
|
||||
var daemonStateRefsPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonStateRefs.cs");
|
||||
var daemonGameSurfaceBuilderPath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonGameSurfaceBuilder.cs");
|
||||
|
|
@ -8701,7 +8700,6 @@ static void RequireDaemonVersePublication(string root)
|
|||
daemonFrameStorePath,
|
||||
daemonPublicationStorePath,
|
||||
daemonSoaDocumentsPath,
|
||||
daemonSoaViewStorePath,
|
||||
daemonSoaFramePublisherPath,
|
||||
daemonStateRefsPath,
|
||||
daemonGameSurfaceBuilderPath,
|
||||
|
|
@ -8736,7 +8734,6 @@ static void RequireDaemonVersePublication(string root)
|
|||
var daemonFrameStore = File.ReadAllText(daemonFrameStorePath);
|
||||
var daemonPublicationStore = File.ReadAllText(daemonPublicationStorePath);
|
||||
var daemonSoaDocuments = File.ReadAllText(daemonSoaDocumentsPath);
|
||||
var daemonSoaViewStore = File.ReadAllText(daemonSoaViewStorePath);
|
||||
var daemonSoaFramePublisher = File.ReadAllText(daemonSoaFramePublisherPath);
|
||||
var daemonStateRefs = File.ReadAllText(daemonStateRefsPath);
|
||||
var daemonGameSurfaceBuilder = File.ReadAllText(daemonGameSurfaceBuilderPath);
|
||||
|
|
@ -8822,7 +8819,7 @@ static void RequireDaemonVersePublication(string root)
|
|||
var requiredSoaFramePublisherSymbols = new[]
|
||||
{
|
||||
"public static class AetheriaRuntimeDaemonSoaFramePublisher",
|
||||
"PublishCurrentZoneEntities(",
|
||||
"BuildCurrentZoneEntities(",
|
||||
"AetheriaRuntimeDaemonSoaBackends.MemoryMappedFile",
|
||||
"MemoryMappedFile.CreateOrOpen(",
|
||||
"ObserverWritable = false",
|
||||
|
|
@ -8831,8 +8828,7 @@ static void RequireDaemonVersePublication(string root)
|
|||
"AetheriaRuntimeDaemonSoaColumnKinds.Velocity",
|
||||
"AetheriaRuntimeDaemonSoaColumnKinds.PhysicsBodyRadius",
|
||||
"AetheriaRuntimeDaemonSoaColumnKinds.RenderVisibility",
|
||||
"AetheriaRuntimeDaemonSoaColumnKinds.RenderGroupId",
|
||||
"AetheriaRuntimeDaemonSoaViewStore.PublishView(stateFilePath, view)"
|
||||
"AetheriaRuntimeDaemonSoaColumnKinds.RenderGroupId"
|
||||
};
|
||||
var missingSoaFramePublisherSymbols = requiredSoaFramePublisherSymbols
|
||||
.Where(symbol => !daemonSoaFramePublisher.Contains(symbol, StringComparison.Ordinal))
|
||||
|
|
@ -8930,13 +8926,18 @@ static void RequireDaemonVersePublication(string root)
|
|||
string.Join(", ", publicationStoreReaderHits));
|
||||
}
|
||||
|
||||
if (daemonFrameStore.Contains("TryReadFrame(", StringComparison.Ordinal) ||
|
||||
daemonFrameStore.Contains("ReadFrame(", StringComparison.Ordinal) ||
|
||||
daemonSoaViewStore.Contains("TryReadView(", StringComparison.Ordinal) ||
|
||||
daemonSoaViewStore.Contains("ReadView(", StringComparison.Ordinal))
|
||||
var daemonSoaViewStorePath = Path.Combine(root, "Packages", "org.gamecult.aetheria.state", "Runtime", "AetheriaRuntimeDaemonSoaViewStore.cs");
|
||||
if (File.Exists(daemonSoaViewStorePath))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Daemon frame/SoA stores still expose file-backed readers; use tick-result documents or AetheriaClient managed observation.");
|
||||
"Daemon SoA latest-view publication must stay on managed CultMesh pointers; delete AetheriaRuntimeDaemonSoaViewStore.cs instead of reviving sidecar path writes.");
|
||||
}
|
||||
|
||||
if (daemonFrameStore.Contains("TryReadFrame(", StringComparison.Ordinal) ||
|
||||
daemonFrameStore.Contains("ReadFrame(", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Daemon frame store still exposes file-backed readers; use tick-result documents or AetheriaClient managed observation.");
|
||||
}
|
||||
|
||||
var requiredDaemonRegistrySymbols = new[]
|
||||
|
|
@ -9111,7 +9112,7 @@ static void RequireDaemonVersePublication(string root)
|
|||
"VerseId",
|
||||
"CultMeshAddress",
|
||||
"AetheriaRuntimeDaemonCommandBoundaryDocument.Create",
|
||||
"AetheriaRuntimeDaemonSoaFramePublisher.PublishCurrentZoneEntities(stateFilePath, frame)",
|
||||
"AetheriaRuntimeDaemonSoaFramePublisher.BuildCurrentZoneEntities(stateFilePath, frame)",
|
||||
"AetheriaRuntimeDaemonProviderAdvertisementDocument.Create",
|
||||
"AetheriaRuntimeDaemonPublicationStore.PublishCommandBoundary",
|
||||
"AetheriaRuntimeDaemonPublicationStore.PublishProviderAdvertisement",
|
||||
|
|
@ -9227,7 +9228,7 @@ static void RequireDaemonVersePublication(string root)
|
|||
? daemonHostSource.Substring(apiPublicationStart, apiPublicationEnd - apiPublicationStart)
|
||||
: "";
|
||||
if (apiPublicationBlock.Contains("AetheriaRuntimeDaemonPublicationStore.TryRead", StringComparison.Ordinal) ||
|
||||
apiPublicationBlock.Contains("AetheriaRuntimeDaemonSoaViewStore.TryRead", StringComparison.Ordinal))
|
||||
apiPublicationBlock.Contains("SoaViewStore.TryRead", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Daemon API document publication must use typed tick result documents instead of reopening witness files.");
|
||||
|
|
@ -13857,7 +13858,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
|
|||
"FramePath",
|
||||
"SoaViewPath",
|
||||
"AetheriaRuntimeDaemonFrameStore.GetFramePath",
|
||||
"AetheriaRuntimeDaemonSoaViewStore.GetViewPath"
|
||||
"SoaViewStore.GetViewPath"
|
||||
};
|
||||
var observedDaemonStateBypassHits = forbiddenObservedDaemonStateSymbols
|
||||
.Where(symbol => observedDaemonState.Contains(symbol, StringComparison.Ordinal))
|
||||
|
|
|
|||
|
|
@ -1941,11 +1941,11 @@ public class DaemonRuntimeDocumentTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void SoaViewStorePublishesLatestDaemonView()
|
||||
public void ManagedLatestSoaViewPublishesLatestDaemonView()
|
||||
{
|
||||
var statePath = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"aetheria-daemon-soa-view-store-tests",
|
||||
"aetheria-managed-soa-view-tests",
|
||||
Path.GetRandomFileName(),
|
||||
"state.cc");
|
||||
var view = AetheriaRuntimeDaemonSoaViewDocument.Create(
|
||||
|
|
@ -1991,22 +1991,32 @@ public class DaemonRuntimeDocumentTests
|
|||
}
|
||||
});
|
||||
|
||||
var viewPath = AetheriaRuntimeDaemonSoaViewStore.PublishView(statePath, view);
|
||||
PublishLatestSoaViewThroughVerseClient(statePath, view);
|
||||
|
||||
Assert.AreEqual(AetheriaRuntimeStateBoundary.GetDaemonSoaViewPath(statePath), viewPath);
|
||||
using var client = AetheriaRuntimeVerseClient
|
||||
.OpenAsync(statePath, "daemon-soa-store-read-test", startServer: false, pullOnOpen: true)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var published = client.LatestSoaView()
|
||||
.ReadAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
|
||||
Assert.IsNotNull(published);
|
||||
Assert.AreEqual(AetheriaRuntimeDaemonSchemas.SoaView, view.Schema);
|
||||
Assert.AreEqual("aetheria-daemon", view.DaemonId);
|
||||
Assert.AreEqual("session-soa-store", view.SessionId);
|
||||
Assert.AreEqual(123, view.FrameId);
|
||||
Assert.AreEqual(456, view.Generation);
|
||||
Assert.IsTrue(view.IsAuthoritative);
|
||||
Assert.AreEqual(1, view.Buffers.Count);
|
||||
Assert.AreEqual("entity-hot-0", view.Buffers[0].BufferId);
|
||||
Assert.IsFalse(view.Buffers[0].ObserverWritable);
|
||||
Assert.AreEqual(1, view.Columns.Count);
|
||||
Assert.AreEqual(AetheriaRuntimeDaemonSoaColumnKinds.Heat, view.Columns[0].Kind);
|
||||
Assert.AreEqual(1, view.DirtyRanges.Count);
|
||||
Assert.AreEqual(256, view.DirtyRanges[0].Count);
|
||||
Assert.AreEqual(AetheriaRuntimeDaemonSchemas.SoaView, published.Schema);
|
||||
Assert.AreEqual("aetheria-daemon", published.DaemonId);
|
||||
Assert.AreEqual("session-soa-store", published.SessionId);
|
||||
Assert.AreEqual(123, published.FrameId);
|
||||
Assert.AreEqual(456, published.Generation);
|
||||
Assert.IsTrue(published.IsAuthoritative);
|
||||
Assert.AreEqual(1, published.Buffers.Count);
|
||||
Assert.AreEqual("entity-hot-0", published.Buffers[0].BufferId);
|
||||
Assert.IsFalse(published.Buffers[0].ObserverWritable);
|
||||
Assert.AreEqual(1, published.Columns.Count);
|
||||
Assert.AreEqual(AetheriaRuntimeDaemonSoaColumnKinds.Heat, published.Columns[0].Kind);
|
||||
Assert.AreEqual(1, published.DirtyRanges.Count);
|
||||
Assert.AreEqual(256, published.DirtyRanges[0].Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -2072,7 +2082,7 @@ public class DaemonRuntimeDocumentTests
|
|||
1.0,
|
||||
0.02);
|
||||
|
||||
var view = AetheriaRuntimeDaemonSoaFramePublisher.PublishCurrentZoneEntities(statePath, frame);
|
||||
var view = AetheriaRuntimeDaemonSoaFramePublisher.BuildCurrentZoneEntities(statePath, frame);
|
||||
Assert.AreEqual(AetheriaRuntimeDaemonSoaBackends.MemoryMappedFile, view.Backend);
|
||||
Assert.AreEqual(1, view.Buffers.Count);
|
||||
Assert.IsFalse(view.Buffers[0].ObserverWritable);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@
|
|||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaRuntimeStateBoot.cs" />
|
||||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaRuntimeVerseHostCommands.cs" />
|
||||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaRuntimeDaemonSurfaceCommands.cs" />
|
||||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaRuntimeDaemonSoaViewStore.cs" />
|
||||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaRuntimePlayerSettingsCommands.cs" />
|
||||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaControl.cs" />
|
||||
<Compile Include="Packages\org.gamecult.aetheria.state\Runtime\AetheriaRuntimeDaemonStateRefs.cs" />
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
new Dictionary<string, RetainedMappedBuffer>(StringComparer.Ordinal);
|
||||
private static long RetainedBufferUseSequence;
|
||||
|
||||
public static AetheriaRuntimeDaemonSoaViewDocument PublishCurrentZoneEntities(
|
||||
public static AetheriaRuntimeDaemonSoaViewDocument BuildCurrentZoneEntities(
|
||||
string stateFilePath,
|
||||
AetheriaRuntimeDaemonFrameDocument frame)
|
||||
{
|
||||
|
|
@ -74,7 +74,6 @@ namespace GameCult.Aetheria.State.Verse
|
|||
synchronizationMode: AetheriaRuntimeDaemonSoaSynchronizationModes.ImmutableFrame,
|
||||
renderGroups: CreateRenderGroups(entities));
|
||||
|
||||
AetheriaRuntimeDaemonSoaViewStore.PublishView(stateFilePath, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
#nullable enable
|
||||
|
||||
namespace GameCult.Aetheria.State.Verse
|
||||
{
|
||||
public static class AetheriaRuntimeDaemonSoaViewStore
|
||||
{
|
||||
public static string GetViewPath(string stateFilePath)
|
||||
{
|
||||
return AetheriaRuntimeStateBoundary.GetDaemonSoaViewPath(stateFilePath);
|
||||
}
|
||||
|
||||
public static string PublishView(string stateFilePath, AetheriaRuntimeDaemonSoaViewDocument view)
|
||||
{
|
||||
var path = GetViewPath(stateFilePath);
|
||||
AetheriaRuntimeCultCacheDocumentStore.WriteDaemonSoaView(path, view);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e7b9b2f5fbcc6fd44b0a7984041a6330
|
||||
|
|
@ -210,7 +210,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
}
|
||||
|
||||
var framePath = AetheriaRuntimeDaemonFrameStore.PublishFrame(stateFilePath, frame);
|
||||
var soaView = AetheriaRuntimeDaemonSoaFramePublisher.PublishCurrentZoneEntities(stateFilePath, frame);
|
||||
var soaView = AetheriaRuntimeDaemonSoaFramePublisher.BuildCurrentZoneEntities(stateFilePath, frame);
|
||||
var commandBoundary = AetheriaRuntimeDaemonCommandBoundaryDocument.Create(options.DaemonId);
|
||||
var commandBoundaryPath = AetheriaRuntimeDaemonPublicationStore.PublishCommandBoundary(
|
||||
stateFilePath,
|
||||
|
|
|
|||
Loading…
Reference in a new issue