refactor(runtime): unify generation reset for direct hosts

Move canonical per-session teardown into one retryable Runtime transaction, reduce App reset to projection acknowledgements, and prove the same GameRuntime graph through deterministic no-window lifecycle, gameplay, portal, fault, reconnect, and isolation gates.\n\nCo-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-27 00:43:26 +02:00
parent 7818494116
commit a9a822f206
28 changed files with 2707 additions and 345 deletions

View file

@ -157,6 +157,7 @@ public sealed class LiveSessionControllerTests
public int ActivateCount { get; private set; }
public List<TestCommandBus> CommandBuses { get; } = [];
public List<LiveSessionCharacterSelection> Selections { get; } = [];
public List<RuntimeGenerationToken> ResetGenerations { get; } = [];
public LiveSessionBinding BindSession(WorldSession session)
{
@ -200,10 +201,12 @@ public sealed class LiveSessionControllerTests
});
}
public void ResetSessionState()
public void ResetSessionState(
RuntimeGenerationToken retiringGeneration)
{
calls.Add("reset");
ResetCount++;
ResetGenerations.Add(retiringGeneration);
OnReset?.Invoke();
if (FailResetOnce)
{
@ -449,6 +452,34 @@ public sealed class LiveSessionControllerTests
Assert.Same(operations.Sessions[1], controller.CurrentSession);
}
[Fact]
public void ResetCallbacksCarryTheExactRetiringScopeGeneration()
{
var calls = new List<string>();
var operations = new TestOperations(calls);
var host = new TestHost(calls);
var controller = new LiveSessionController(operations);
LiveSessionStartResult first =
controller.Start(LiveOptions(), host);
RuntimeGenerationToken firstGeneration = controller.Generation;
LiveSessionStartResult second =
controller.Reconnect(LiveOptions(), host);
RuntimeGenerationToken secondGeneration = controller.Generation;
controller.Stop();
Assert.Equal(LiveSessionStartStatus.Connected, first.Status);
Assert.Equal(LiveSessionStartStatus.Connected, second.Status);
Assert.Equal(
[
RuntimeGenerationToken.Initial,
firstGeneration,
secondGeneration,
],
host.ResetGenerations);
Assert.NotEqual(firstGeneration, secondGeneration);
}
[Theory]
[InlineData("detach", "stop")]
[InlineData("detach", "dispose")]