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:
parent
7818494116
commit
a9a822f206
28 changed files with 2707 additions and 345 deletions
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ public sealed class LiveSessionHostTests
|
|||
Func<WorldSession, ILiveSessionCommandRouting> createCommands) =>
|
||||
new(controller, new LiveSessionHostBindings(
|
||||
Routing: new(createEvents, createCommands),
|
||||
Reset: () => calls.Add("reset"),
|
||||
Reset: _ => calls.Add("reset"),
|
||||
Selection: new(
|
||||
id => calls.Add($"player:{id}"),
|
||||
id => calls.Add($"vitals:{id}"),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public sealed class LiveSessionLifecycleHostTests
|
|||
var host = CreateHost(calls);
|
||||
|
||||
LiveSessionBinding binding = host.BindSession(sessionA);
|
||||
host.ResetSessionState();
|
||||
host.ResetSessionState(RuntimeGenerationToken.Initial);
|
||||
host.ReportConnecting("host", 9000, "user");
|
||||
host.ReportConnected();
|
||||
var selection = new LiveSessionCharacterSelection(2, 3u, "toon", "account");
|
||||
|
|
@ -67,7 +67,7 @@ public sealed class LiveSessionLifecycleHostTests
|
|||
Func<WorldSession, LiveSessionBinding>? bind = null) =>
|
||||
new(new LiveSessionLifecycleBindings(
|
||||
Bind: bind ?? (session => CreateBinding(session, calls)),
|
||||
Reset: () => calls.Add("reset"),
|
||||
Reset: _ => calls.Add("reset"),
|
||||
Connecting: (host, port, user) =>
|
||||
calls.Add($"connecting:{host}:{port}:{user}"),
|
||||
Connected: () => calls.Add("connected"),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public sealed class RuntimeLiveSessionNoWindowTests
|
|||
new LiveSessionRoutingFactories(
|
||||
_ => new EventRoute(calls),
|
||||
_ => new CommandRoute(calls)),
|
||||
() => calls.Add("reset"),
|
||||
_ => calls.Add("reset"),
|
||||
new LiveSessionSelectionBindings(
|
||||
id => calls.Add($"player:{id}"),
|
||||
_ => { },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue