Skip to content

Dev/mdaigle/pool rate limit#4376

Draft
mdaigle wants to merge 25 commits into
mainfrom
dev/mdaigle/pool-rate-limit
Draft

Dev/mdaigle/pool rate limit#4376
mdaigle wants to merge 25 commits into
mainfrom
dev/mdaigle/pool-rate-limit

Conversation

@mdaigle

@mdaigle mdaigle commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Description

Provide a summary of the changes being introduced. Important topics to cover
include:

  • Description of the functionality.
  • API changes, backwards compatibility, deprecations, etc.
  • Documentation, localization.
  • Bug fixes.
  • Code hygiene, refactoring, improvements.
  • Engineering processes (CI, pipelines, test coverage)

High quality descriptions will lead to a smoother review experience.

Issues

Link to any relevant issues, bugs, or discussions (e.g., Closes #123, Fixes issue #456).

Testing

Describe the automated tests (unit, integration) you created or modified.
Provide justification for any gap in automated testing. List any manual testing
steps that were performed to ensure the changes work. 

Guidelines

Please review the contribution guidelines before submitting a pull request:

Copilot AI review requested due to automatic review settings June 18, 2026 21:35
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Jun 18, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds infrastructure for connection-pool rate limiting and aligns both pool implementations on a shared “blocking period” error-state mechanism (fast-fail after connection-creation failures with exponential backoff), with accompanying unit tests and a draft spec.

Changes:

  • Introduces BlockingPeriodErrorState and integrates it into both ChannelDbConnectionPool and WaitHandleDbConnectionPool.
  • Adds initial plumbing for connection-creation rate limiting in ChannelDbConnectionPool (plus NoOpAcquiredLease).
  • Adds unit tests and a feature spec/diagram documenting intended behavior.

Reviewed changes

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

Show a summary per file
File Description
src/Microsoft.Data.SqlClient/tests/UnitTests/ConnectionPool/ChannelDbConnectionPoolTest.cs Adds unit tests for blocking period behavior and rate-limit lease disposal scenarios.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/WaitHandleDbConnectionPool.cs Refactors blocking-period logic to use the shared BlockingPeriodErrorState and pool-group policy helper.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/NoOpAcquiredLease.cs Adds a singleton no-op RateLimitLease used when no limiter is configured.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/DbConnectionPoolGroup.cs Centralizes blocking-period enablement policy in IsBlockingPeriodEnabled().
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/ChannelDbConnectionPool.cs Adds blocking-period error state support and rate-limit acquisition logic on connection creation.
src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/BlockingPeriodErrorState.cs New shared implementation for cached error + exponential backoff + timer-based recovery.
src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj Adds System.Threading.RateLimiting package reference.
specs/006-pool-rate-limiting/spec.md Draft feature specification for rate limiting + blocking period semantics.
specs/006-pool-rate-limiting/diagrams.md Mermaid diagrams comparing old vs new pool throttling approach.
Directory.Packages.props Adds central package version entry for System.Threading.RateLimiting.

@mdaigle mdaigle added this to the 7.1.0-preview2 milestone Jun 18, 2026
Copilot AI review requested due to automatic review settings June 22, 2026 18:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 6 comments.

@mdaigle

mdaigle commented Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

@copilot add a System.Threading.RateLimiting dependency in the manual tests project

Co-authored-by: mdaigle <4722049+mdaigle@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 22, 2026 22:25
@mdaigle mdaigle removed the request for review from Copilot June 22, 2026 22:25

Copilot AI commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

@copilot add a System.Threading.RateLimiting dependency in the manual tests project

Added System.Threading.RateLimiting to the ManualTests project for both net462 and non-net462 target groups in commit 72c080c.

Copilot AI review requested due to automatic review settings June 23, 2026 16:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Comment on lines +1774 to +1795
/// <summary>
{
/// <summary>
/// Gets the number of times the pool asked the factory to create a physical connection.
/// </summary>
internal int CreateCount { get; private set; }

/// <summary>
/// Creates a successful stub internal connection and increments the creation counter.
/// </summary>
protected override DbConnectionInternal CreateConnection(
SqlConnectionOptions options,
ConnectionPoolKey poolKey,
DbConnectionPoolGroupProviderInfo poolGroupProviderInfo,
IDbConnectionPool pool,
DbConnection owningConnection,
TimeoutTimer timeout)
{
CreateCount++;
return new StubDbConnectionInternal();
}
}
Comment on lines +98 to +110
// Create the exit timer disarmed (infinite due time); it is armed below outside
// the lock. ADP.UnsafeCreateTimer suppresses execution-context flow so the timer
// doesn't capture and pin the current ExecutionContext and its AsyncLocals for its
// lifetime, while still honoring the injected TimeProvider for testability.
newTimer = ADP.UnsafeCreateTimer(
_timeProvider,
ExitCallback,
null,
Timeout.InfiniteTimeSpan,
Timeout.InfiniteTimeSpan);
oldTimer = _exitTimer;
_exitTimer = newTimer;

BlockingPeriodErrorState calls a 5-arg UnsafeCreateTimer(TimeProvider, ...) returning ITimer that was missing from AdapterUtil, breaking the build. Re-add the overload, which suppresses ExecutionContext flow while honoring the injected TimeProvider for testability.
Copilot AI review requested due to automatic review settings June 23, 2026 17:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Comment on lines +1996 to +2017
/// <summary>
{
/// <summary>
/// Gets the number of times the pool asked the factory to create a physical connection.
/// </summary>
internal int CreateCount { get; private set; }

/// <summary>
/// Creates a successful stub internal connection and increments the creation counter.
/// </summary>
protected override DbConnectionInternal CreateConnection(
SqlConnectionOptions options,
ConnectionPoolKey poolKey,
DbConnectionPoolGroupProviderInfo poolGroupProviderInfo,
IDbConnectionPool pool,
DbConnection owningConnection,
TimeoutTimer timeout)
{
CreateCount++;
return new StubDbConnectionInternal();
}
}
// waiting on the idle channel, where it can be satisfied either by a
// returning connection or by a null poke from another caller releasing
// its rate-limit lease (see finally below). We prefer to recycle existing
// connections rather then queue on the rate limit. When no limiter is
Comment on lines +70 to +71
While in the error state the pool waits using exponential backoff (5s → 10s → 20s → 30s → 60s
cap) before allowing the next attempt. Once an attempt after the backoff succeeds, the error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To triage

Development

Successfully merging this pull request may close these issues.

3 participants