Use reactive frame inputs for Verse projections
This commit is contained in:
parent
dd68efd9cd
commit
1f066b793b
3 changed files with 32 additions and 16 deletions
|
|
@ -10741,8 +10741,10 @@ static void RequireAetheriaRuntimeVerseClientContract(string root)
|
|||
"loadoutTemplatesDocument.Reactive()",
|
||||
"starbridgeScenarioDocument.Reactive()",
|
||||
"starbridgeSessionDocument.Reactive()",
|
||||
"latestFrameDocument.Reactive()",
|
||||
"BootstrapRuntimeCatalogSnapshot(),",
|
||||
"BootstrapLoadoutTemplatesDocument())",
|
||||
"projectionInputs.RequireFrame()",
|
||||
"projectionInputs.Catalog",
|
||||
"projectionInputs.LoadoutTemplates.Templates",
|
||||
"projectionInputs.StarbridgeScenario",
|
||||
|
|
@ -10787,6 +10789,13 @@ static void RequireAetheriaRuntimeVerseClientContract(string root)
|
|||
"Aetheria runtime Verse client Starbridge projection still polls sibling documents instead of sampling managed reactive projection inputs.");
|
||||
}
|
||||
|
||||
if (client.Contains("RequireFrameAsync", StringComparison.Ordinal) ||
|
||||
client.Contains("Aetheria().Daemon.LatestFrame.LatestAsync()", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Aetheria runtime Verse client projected documents still bootstrap through one-shot latest-frame reads instead of the managed reactive projection inputs.");
|
||||
}
|
||||
|
||||
var requiredClientStateSymbols = new[]
|
||||
{
|
||||
"public Func<string, string> CreateEveSurfaceStateRefResolver()",
|
||||
|
|
@ -14766,7 +14775,9 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
|
|||
var requiredManagedClientConnectionSymbols = new[]
|
||||
{
|
||||
"public AetheriaClientState State => _state;",
|
||||
"public AetheriaClientState Aetheria() => State;"
|
||||
"public AetheriaClientState Aetheria() => State;",
|
||||
"using var observedState = State.ReactiveObservedDaemon();",
|
||||
"observedState.TryCurrent(out var current)"
|
||||
};
|
||||
var missingManagedClientConnectionSymbols = requiredManagedClientConnectionSymbols
|
||||
.Where(symbol => !aetheriaClient.Contains(symbol, StringComparison.Ordinal))
|
||||
|
|
@ -14840,6 +14851,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
|
|||
|
||||
var forbiddenDaemonClientBypassSymbols = new[]
|
||||
{
|
||||
".ReadAsync(State)",
|
||||
"return _verse.GetObservedDaemonStateAsync();",
|
||||
"return _verse.GetLatestAuthoritativeRunFrameAsync();",
|
||||
"return _verse.GetHealthAsync();",
|
||||
|
|
|
|||
|
|
@ -161,10 +161,10 @@ namespace GameCult.Aetheria.State.Verse
|
|||
ThrowIfDisposed();
|
||||
if (submit == null) throw new ArgumentNullException(nameof(submit));
|
||||
|
||||
var observed = AetheriaRuntimeObservedDaemonState
|
||||
.ReadAsync(State)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
using var observedState = State.ReactiveObservedDaemon();
|
||||
var observed = observedState.TryCurrent(out var current)
|
||||
? current
|
||||
: null;
|
||||
var operationClient = new AetheriaRuntimeDaemonOperationClient(
|
||||
StatePath,
|
||||
_clientId,
|
||||
|
|
|
|||
|
|
@ -544,7 +544,10 @@ namespace GameCult.Aetheria.State.Verse
|
|||
AetheriaRuntimeVerseRecordKeys.StarbridgeScenarioLatest);
|
||||
var starbridgeSessionDocument = Document<AetheriaRuntimeStarbridgeSessionDocument>(
|
||||
AetheriaRuntimeVerseRecordKeys.StarbridgeSessionLatest);
|
||||
var latestFrameDocument = Document<AetheriaRuntimeDaemonFrameDocument>(
|
||||
AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest);
|
||||
var projectionInputs = new AetheriaRuntimeReactiveProjectionInputs(
|
||||
latestFrameDocument.Reactive(),
|
||||
catalogDocument.Reactive(),
|
||||
loadoutTemplatesDocument.Reactive(),
|
||||
starbridgeScenarioDocument.Reactive(),
|
||||
|
|
@ -562,8 +565,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
AetheriaRuntimeVerseRecordKeys.DaemonCommandBoundary),
|
||||
Document<AetheriaRuntimeVerseAuthorityPolicyDocument>(
|
||||
AetheriaRuntimeVerseRecordKeys.VerseAuthorityPolicy),
|
||||
Document<AetheriaRuntimeDaemonFrameDocument>(
|
||||
AetheriaRuntimeVerseRecordKeys.DaemonFrameLatest),
|
||||
latestFrameDocument,
|
||||
Document<AetheriaRuntimeDaemonSoaViewDocument>(
|
||||
AetheriaRuntimeVerseRecordKeys.DaemonSoaViewLatest),
|
||||
Document<EveSurfaceState>(
|
||||
|
|
@ -678,7 +680,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return CultMesh.Document(
|
||||
documentId,
|
||||
verse,
|
||||
async _ => await project(await RequireFrameAsync().ConfigureAwait(false)).ConfigureAwait(false),
|
||||
async _ => await project(projectionInputs.RequireFrame()).ConfigureAwait(false),
|
||||
_ => frameChanges
|
||||
.SelectAwait(async (frame, cancellationToken) =>
|
||||
await project(frame).ConfigureAwait(false)),
|
||||
|
|
@ -754,14 +756,6 @@ namespace GameCult.Aetheria.State.Verse
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<AetheriaRuntimeDaemonFrameDocument> RequireFrameAsync()
|
||||
{
|
||||
var frame = await Aetheria().Daemon.LatestFrame.LatestAsync().ConfigureAwait(false);
|
||||
if (frame == null)
|
||||
throw new InvalidOperationException("Aetheria Verse client has no daemon frame yet.");
|
||||
return frame;
|
||||
}
|
||||
|
||||
private CultMeshMutableStatePointer<T> MutableDocumentPointer<T>(CultRecordKey key) where T : class
|
||||
{
|
||||
return CultMesh.MutableStatePointer(
|
||||
|
|
@ -786,6 +780,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
|
||||
private sealed class AetheriaRuntimeReactiveProjectionInputs : IDisposable
|
||||
{
|
||||
private readonly CultMeshReactiveDocument<AetheriaRuntimeDaemonFrameDocument> _daemonFrame;
|
||||
private readonly CultMeshReactiveDocument<AetheriaRuntimeCatalogSnapshot> _catalog;
|
||||
private readonly CultMeshReactiveDocument<AetheriaRuntimeLoadoutTemplatesDocument> _loadoutTemplates;
|
||||
private readonly CultMeshReactiveDocument<AetheriaRuntimeStarbridgeScenarioDocument> _starbridgeScenario;
|
||||
|
|
@ -794,6 +789,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
private readonly AetheriaRuntimeLoadoutTemplatesDocument _fallbackLoadoutTemplates;
|
||||
|
||||
public AetheriaRuntimeReactiveProjectionInputs(
|
||||
CultMeshReactiveDocument<AetheriaRuntimeDaemonFrameDocument> daemonFrame,
|
||||
CultMeshReactiveDocument<AetheriaRuntimeCatalogSnapshot> catalog,
|
||||
CultMeshReactiveDocument<AetheriaRuntimeLoadoutTemplatesDocument> loadoutTemplates,
|
||||
CultMeshReactiveDocument<AetheriaRuntimeStarbridgeScenarioDocument> starbridgeScenario,
|
||||
|
|
@ -801,6 +797,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
AetheriaRuntimeCatalogSnapshot fallbackCatalog,
|
||||
AetheriaRuntimeLoadoutTemplatesDocument fallbackLoadoutTemplates)
|
||||
{
|
||||
_daemonFrame = daemonFrame ?? throw new ArgumentNullException(nameof(daemonFrame));
|
||||
_catalog = catalog ?? throw new ArgumentNullException(nameof(catalog));
|
||||
_loadoutTemplates = loadoutTemplates ?? throw new ArgumentNullException(nameof(loadoutTemplates));
|
||||
_starbridgeScenario = starbridgeScenario ?? throw new ArgumentNullException(nameof(starbridgeScenario));
|
||||
|
|
@ -814,8 +811,15 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public AetheriaRuntimeStarbridgeScenarioDocument? StarbridgeScenario => _starbridgeScenario.Current;
|
||||
public AetheriaRuntimeStarbridgeSessionDocument? StarbridgeSession => _starbridgeSession.Current;
|
||||
|
||||
public AetheriaRuntimeDaemonFrameDocument RequireFrame()
|
||||
{
|
||||
return _daemonFrame.Current
|
||||
?? throw new InvalidOperationException("Aetheria Verse client has no daemon frame yet.");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_daemonFrame.Dispose();
|
||||
_catalog.Dispose();
|
||||
_loadoutTemplates.Dispose();
|
||||
_starbridgeScenario.Dispose();
|
||||
|
|
|
|||
Loading…
Reference in a new issue