Skip to content

Commit ad67cd3

Browse files
committed
Preserve session routing after failed resume
Capture the wrapper displaced before session.resume and restore it only if the failed replacement is still registered. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c71188a1-1445-46aa-9faf-3b73cf6a6dd9
1 parent 5f94e8b commit ad67cd3

2 files changed

Lines changed: 33 additions & 9 deletions

File tree

dotnet/src/Client.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -774,8 +774,10 @@ private CopilotSession InitializeSession(
774774
Dictionary<string, Func<string, Task<string>>>? transformCallbacks,
775775
bool hasHooks,
776776
string callerName,
777-
bool replaceExisting = false)
777+
bool replaceExisting,
778+
out CopilotSession? replacedSession)
778779
{
780+
replacedSession = null;
779781
var setupTimestamp = Stopwatch.GetTimestamp();
780782
var session = new CopilotSession(
781783
sessionId,
@@ -810,7 +812,16 @@ private CopilotSession InitializeSession(
810812
session.RegisterBearerTokenProviders(BuildBearerTokenCallbacks(config));
811813
if (replaceExisting)
812814
{
813-
_sessions[session.SessionId] = session;
815+
CopilotSession? displacedSession = null;
816+
_sessions.AddOrUpdate(
817+
session.SessionId,
818+
session,
819+
(_, current) =>
820+
{
821+
displacedSession = current;
822+
return session;
823+
});
824+
replacedSession = displacedSession;
814825
}
815826
else if (!_sessions.TryAdd(session.SessionId, session))
816827
{
@@ -1128,7 +1139,9 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
11281139
config,
11291140
transformCallbacks,
11301141
hasHooks,
1131-
"CopilotClient.CreateSessionAsync");
1142+
"CopilotClient.CreateSessionAsync",
1143+
replaceExisting: false,
1144+
out _);
11321145
}
11331146
try
11341147
{
@@ -1228,7 +1241,9 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
12281241
config,
12291242
transformCallbacks,
12301243
hasHooks,
1231-
"CopilotClient.CreateSessionAsync");
1244+
"CopilotClient.CreateSessionAsync",
1245+
replaceExisting: false,
1246+
out _);
12321247
}
12331248
};
12341249

@@ -1344,7 +1359,8 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
13441359
transformCallbacks,
13451360
hasHooks,
13461361
"CopilotClient.ResumeSessionAsync",
1347-
replaceExisting: true);
1362+
replaceExisting: true,
1363+
out var previousSession);
13481364
try
13491365
{
13501366
var (traceparent, tracestate) = TelemetryHelpers.GetTraceContext();
@@ -1443,7 +1459,15 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
14431459
}
14441460
catch (Exception ex)
14451461
{
1446-
session.RemoveFromClient();
1462+
if (previousSession is null)
1463+
{
1464+
session.RemoveFromClient();
1465+
}
1466+
else
1467+
{
1468+
_sessions.TryUpdate(sessionId, previousSession, session);
1469+
}
1470+
14471471
if (ex is not OperationCanceledException)
14481472
{
14491473
LoggingHelpers.LogTiming(_logger, LogLevel.Warning, ex,

dotnet/test/Unit/ClientSessionLifetimeTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public async Task ResumeSessionAsync_Replaces_Session_Tracked_By_Same_Client()
216216
}
217217

218218
[Fact]
219-
public async Task Failed_ResumeSessionAsync_Removes_Replacement_Registration()
219+
public async Task Failed_ResumeSessionAsync_Restores_Previous_Registration()
220220
{
221221
await using var server = await FakeCopilotServer.StartAsync();
222222
await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) });
@@ -234,8 +234,8 @@ public async Task Failed_ResumeSessionAsync_Removes_Replacement_Registration()
234234
OnPermissionRequest = PermissionHandler.ApproveAll
235235
}));
236236

237-
AssertSessionCount(client, sessions: 0);
238-
Assert.Null(GetTrackedSession(client, sessionId));
237+
AssertSessionCount(client, sessions: 1);
238+
Assert.Same(session, GetTrackedSession(client, sessionId));
239239
Assert.Equal("message-1", await session.SendAsync("The original session remains active."));
240240

241241
await session.DisposeAsync();

0 commit comments

Comments
 (0)