Preserve framed reads across fake worker emission gates
ci / windows-x86 (push) Successful in 1m20s
ci / nightly-windev (push) Has been skipped
ci / java (push) Successful in 2m17s
ci / windows-x86 (pull_request) Successful in 1m25s
ci / nightly-windev (pull_request) Has been skipped
ci / java (pull_request) Successful in 2m27s
ci / portable (push) Successful in 9m43s
ci / portable (pull_request) Successful in 9m47s
ci / windows-x86 (push) Successful in 1m20s
ci / nightly-windev (push) Has been skipped
ci / java (push) Successful in 2m17s
ci / windows-x86 (pull_request) Successful in 1m25s
ci / nightly-windev (pull_request) Has been skipped
ci / java (pull_request) Successful in 2m27s
ci / portable (push) Successful in 9m43s
ci / portable (pull_request) Successful in 9m47s
This commit is contained in:
@@ -478,24 +478,42 @@ public sealed class SessionManagerTests
|
||||
[Fact]
|
||||
public async Task InvokeAsync_WhenWorkerHandshakingThenReadyWithinTimeout_Succeeds()
|
||||
{
|
||||
FakeTimeProvider clock = new(new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
FakeWorkerClient workerClient = new() { State = WorkerClientState.Handshaking };
|
||||
SessionManager manager = CreateManager(
|
||||
new FakeSessionWorkerClientFactory(workerClient),
|
||||
options: CreateOptions(workerReadyWaitTimeoutMs: 500));
|
||||
options: CreateOptions(workerReadyWaitTimeoutMs: 500),
|
||||
timeProvider: clock);
|
||||
GatewaySession session = await manager.OpenSessionAsync(CreateOpenRequest(), "client-1", ownerKeyId: null, CancellationToken.None);
|
||||
Assert.Equal(SessionState.Ready, session.State);
|
||||
|
||||
// Flip the worker to Ready shortly after the invoke starts waiting.
|
||||
_ = Task.Run(async () =>
|
||||
TaskCompletionSource handshakingObserved = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
TaskCompletionSource allowReady = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
workerClient.OnStateRead = state =>
|
||||
{
|
||||
await Task.Delay(50, CancellationToken.None);
|
||||
workerClient.State = WorkerClientState.Ready;
|
||||
});
|
||||
|
||||
WorkerCommandReply reply = await manager.InvokeAsync(
|
||||
if (state == WorkerClientState.Handshaking)
|
||||
{
|
||||
handshakingObserved.TrySetResult();
|
||||
}
|
||||
};
|
||||
Task transition = TransitionAsync();
|
||||
Task<WorkerCommandReply> invoke = manager.InvokeAsync(
|
||||
session.SessionId,
|
||||
CreateCommand(MxCommandKind.Ping),
|
||||
CancellationToken.None);
|
||||
await handshakingObserved.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
Assert.False(invoke.IsCompleted);
|
||||
Assert.Equal(0, workerClient.InvokeCount);
|
||||
allowReady.SetResult();
|
||||
await transition.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
clock.Advance(TimeSpan.FromMilliseconds(50));
|
||||
WorkerCommandReply reply = await invoke.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
async Task TransitionAsync()
|
||||
{
|
||||
await allowReady.Task;
|
||||
workerClient.State = WorkerClientState.Ready;
|
||||
}
|
||||
|
||||
Assert.NotNull(reply);
|
||||
Assert.Equal(1, workerClient.InvokeCount);
|
||||
@@ -1406,14 +1424,28 @@ public sealed class SessionManagerTests
|
||||
|
||||
private sealed class FakeWorkerClient : IWorkerClient
|
||||
{
|
||||
private WorkerClientState _state = WorkerClientState.Ready;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SessionId { get; init; } = "session-1";
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? ProcessId { get; init; } = 1234;
|
||||
|
||||
/// <summary>Gets or sets the optional state-observation gate.</summary>
|
||||
public Action<WorkerClientState>? OnStateRead { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public WorkerClientState State { get; set; } = WorkerClientState.Ready;
|
||||
public WorkerClientState State
|
||||
{
|
||||
get
|
||||
{
|
||||
OnStateRead?.Invoke(_state);
|
||||
return _state;
|
||||
}
|
||||
|
||||
set => _state = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTimeOffset LastHeartbeatAt { get; init; } = DateTimeOffset.UtcNow;
|
||||
|
||||
Reference in New Issue
Block a user