Skip to content

CSHARP-6029: Make ICoreServerSessionPool disposable and send endSessions on dispose#1995

Open
sanych-sun wants to merge 4 commits into
mongodb:mainfrom
sanych-sun:CSHARP-6029
Open

CSHARP-6029: Make ICoreServerSessionPool disposable and send endSessions on dispose#1995
sanych-sun wants to merge 4 commits into
mongodb:mainfrom
sanych-sun:CSHARP-6029

Conversation

@sanych-sun
Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings May 9, 2026 00:26
@sanych-sun sanych-sun requested a review from a team as a code owner May 9, 2026 00:26
@sanych-sun sanych-sun added the bug Fixes issues or unintended behavior. label May 9, 2026
@sanych-sun sanych-sun requested review from BorisDog and ajcvickers and removed request for ajcvickers May 9, 2026 00:26
@sanych-sun sanych-sun marked this pull request as draft May 9, 2026 00:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to ensure server-side sessions are explicitly ended when a client/cluster is disposed (via an endSessions command), and adjusts test event capture behavior to avoid capturing disposal-time commands.

Changes:

  • Added session-pool draining logic that issues endSessions for pooled server sessions during cluster disposal.
  • Introduced EventCapturer.Stop() and invoked it from the JSON-driven spec test runner.
  • Added a shared helper on Cluster to select an available server and trigger session-pool cleanup during disposal.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/MongoDB.Driver.Tests/Specifications/Runner/MongoClientJsonDrivenTestRunnerBase.cs Stops event capture after test operations complete.
tests/MongoDB.Driver.TestHelpers/Core/EventCapturer.cs Adds a stop flag to disable capturing after disposal begins.
src/MongoDB.Driver/Core/Clusters/SingleServerCluster.cs Triggers session-pool cleanup before server removal on dispose.
src/MongoDB.Driver/Core/Clusters/MultiServerCluster.cs Triggers session-pool cleanup during cluster disposal.
src/MongoDB.Driver/Core/Clusters/Cluster.cs Adds ReleaseServerSessionPool() helper to drive cleanup.
src/MongoDB.Driver/Core/Bindings/ICoreServerSessionPool.cs Extends pool contract with ReleaseAll(IServer).
src/MongoDB.Driver/Core/Bindings/CoreServerSessionPool.cs Implements ReleaseAll to drain pooled sessions and send endSessions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


ExecuteOperations(client, objectMap: null, test, eventCapturer);

eventCapturer.Stop();
Comment thread tests/MongoDB.Driver.TestHelpers/Core/EventCapturer.cs
Comment on lines +128 to +142
var operationContext = OperationContext.NoTimeout;
using var channel = server.GetChannel(operationContext);
channel.Command(
operationContext,
NoCoreSession.Instance,
ReadPreference.PrimaryPreferred,
DatabaseNamespace.Admin,
endSessionCommand,
null,
NoOpElementNameValidator.Instance,
null,
null,
CommandResponseHandling.Return,
BsonDocumentSerializer.Instance,
null);
Comment on lines +99 to +120
public void ReleaseAll(IServer server)
{
if (_pool.Count == 0)
{
return;
}

try
{
while (true)
{
List<ICoreServerSession> sessionsBatch;
lock (_lock)
{
if (_pool.Count == 0)
{
return;
}

sessionsBatch = _pool.GetRange(0, Math.Min(_pool.Count, 9999));
_pool.RemoveRange(0, sessionsBatch.Count);
}
Comment on lines +116 to +120
}

sessionsBatch = _pool.GetRange(0, Math.Min(_pool.Count, 9999));
_pool.RemoveRange(0, sessionsBatch.Count);
}
Comment on lines +99 to +149
public void ReleaseAll(IServer server)
{
if (_pool.Count == 0)
{
return;
}

try
{
while (true)
{
List<ICoreServerSession> sessionsBatch;
lock (_lock)
{
if (_pool.Count == 0)
{
return;
}

sessionsBatch = _pool.GetRange(0, Math.Min(_pool.Count, 9999));
_pool.RemoveRange(0, sessionsBatch.Count);
}

var endSessionCommand = new BsonDocument("endSessions", new BsonArray(sessionsBatch.Select(s => s.Id)));
foreach (var session in sessionsBatch)
{
session.Dispose();
}

var operationContext = OperationContext.NoTimeout;
using var channel = server.GetChannel(operationContext);
channel.Command(
operationContext,
NoCoreSession.Instance,
ReadPreference.PrimaryPreferred,
DatabaseNamespace.Admin,
endSessionCommand,
null,
NoOpElementNameValidator.Instance,
null,
null,
CommandResponseHandling.Return,
BsonDocumentSerializer.Instance,
null);
}
}
catch
{
// Ignore any errors.
}
}
Comment on lines +20 to 25
internal interface ICoreServerSessionPool
{
internal interface ICoreServerSessionPool
{
ICoreServerSession AcquireSession();
void ReleaseSession(ICoreServerSession serverSession);
}
ICoreServerSession AcquireSession();
void ReleaseSession(ICoreServerSession serverSession);
void ReleaseAll(IServer server);
}
using System.Collections.Generic;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Bson.IO;
@sanych-sun sanych-sun marked this pull request as ready for review May 22, 2026 03:10
private readonly object _lock = new object();
private readonly List<ICoreServerSession> _pool = new List<ICoreServerSession>();
private readonly ILogger<LogCategories.Client> _logger;
private readonly ConcurrentStack<ICoreServerSession> _pool = new();
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accordingly to spec pool should be LIFO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Fixes issues or unintended behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants