Skip to content

Connect timeout propagated through pool#4270

Merged
mdaigle merged 41 commits into
mainfrom
dev/mdaigle/pool-timeouts
May 29, 2026
Merged

Connect timeout propagated through pool#4270
mdaigle merged 41 commits into
mainfrom
dev/mdaigle/pool-timeouts

Conversation

@mdaigle

@mdaigle mdaigle commented May 11, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces improvements to connection timeout handling in the SQL client by switching from simple timeouts to a more robust TimeoutTimer system. It also adds the Microsoft.Bcl.TimeProvider dependency, and updates several method signatures to consistently propagate the timeout budget across connection creation and pooling logic. These changes help ensure that the total timeout budget is respected throughout the connection process, improving reliability and observability for connection attempts.

Dependency updates:

  • Added Microsoft.Bcl.TimeProvider as a dependency in both the solution's package version list and the main project file to support advanced timeout handling. [1] [2] [3]

Timeout handling improvements:

  • Replaced usages of raw timeouts with the TimeoutTimer class throughout the connection and pooling code, ensuring that the overall timeout budget is consistently tracked and enforced during connection attempts and retries. [1] [2] [3] [4] [5]
  • Updated connection pool methods such as TryGetConnection and GetInternalConnection to accept and use a TimeoutTimer instead of a TimeSpan, and to derive cancellation tokens from the timer for accurate timeout enforcement. [1] [2]

API and signature changes:

  • Updated method signatures for connection opening and replacement (e.g., TryOpenConnection, TryReplaceConnection, and related overrides) to include the TimeoutTimer parameter, ensuring the timeout is propagated through all relevant layers. [1] [2] [3] [4] [5]

Connection creation and pooling:

  • Modified the connection pool's internal logic to pass the TimeoutTimer through to the physical connection factory, so that time spent waiting in the pool is deducted from the overall connection timeout budget. [1] [2] [3]

Code cleanup and comments:

  • Added comments and TODOs to clarify timeout propagation and highlight areas for future improvement (e.g., passing cancellation tokens deeper into the connection factory). [1] [2]

These changes collectively improve the accuracy and reliability of connection timeouts, making the client's behavior more predictable under high load or slow network conditions.

mdaigle and others added 2 commits May 11, 2026 15:13
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings May 11, 2026 23:18
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board May 11, 2026

This comment was marked as outdated.

mdaigle and others added 4 commits May 12, 2026 13:15
Thread a single TimeoutTimer from SqlConnection.Open through
DbConnectionInternal/DbConnectionClosed -> SqlConnectionFactory ->
IDbConnectionPool implementations down to physical connection creation.
Replaces per-layer TimeoutTimer construction.

- DbConnectionInternal: OpenConnection creates the timer; TryOpenConnection,
  TryReplaceConnection, TryOpenConnectionInternal accept TimeoutTimer.
- DbConnectionClosed/SqlConnectionInternal: signature pass-through.
- SqlConnectionFactory: TryGetConnection, CreateNonPooledConnection, and
  CreateReplaceConnectionContinuation accept and forward TimeoutTimer.
- IDbConnectionPool: TryGetConnection/ReplaceConnection now require
  TimeoutTimer.
- ChannelDbConnectionPool: removes its local timer creation; uses caller's.
- WaitHandleDbConnectionPool: PendingGetConnection carries TimeoutTimer;
  CreateObject/UserCreateRequest/ReplaceConnection accept it. Maintenance
  worker uses CreationTimeout-based timer.
- SqlConnection.TryOpenInner: creates the TimeoutTimer for the open path.
- Tests: TransactedConnectionPoolTest mock updated; new PoolTestExtensions
  provides legacy 3-arg overloads that derive the timer from
  owningObject.ConnectionTimeout for existing test call sites.
Add an overload TimeoutTimer.StartNew(TimeSpan, TimeProvider) and route
all clock reads (current time, expiration check, remaining ms, Reset)
plus CreateCancellationTokenSource through the supplied TimeProvider.
The existing parameterless StartNew now delegates to TimeProvider.System,
preserving behavior for production call sites.

This lets tests inject Microsoft.Extensions.Time.Testing.FakeTimeProvider
and trigger timeout / cancellation behavior by advancing virtual time,
removing wall-clock dependence and timing flakiness.

- TimeoutTimer: store TimeProvider, derive ExpirationTicks via
  timeProvider.GetUtcNow().UtcDateTime.ToFileTimeUtc() (file-time scale
  preserved for compatibility with TdsParser consumers); CTS scheduled via
  new CancellationTokenSource(TimeSpan, TimeProvider).
- src.csproj: add Microsoft.Bcl.TimeProvider for the net462 TFM (required
  for the System.TimeProvider type on .NET Framework).
- UnitTests.csproj: add Microsoft.Extensions.TimeProvider.Testing for
  FakeTimeProvider.
- Directory.Packages.props: pin both packages.
- Add TimeoutTimerTimeProviderTests covering: System default, null guard,
  IsExpired/MillisecondsRemaining advancement, Reset, CTS firing on
  virtual-time advance, already-expired CTS, infinite timer, and the
  TimeProvider property accessor.
Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings May 12, 2026 22:37

This comment was marked as outdated.

mdaigle and others added 3 commits May 12, 2026 16:10
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings May 12, 2026 23:33

This comment was marked as outdated.

mdaigle and others added 5 commits May 12, 2026 16:52
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings May 13, 2026 00:07

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 17 out of 17 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ConnectionPool/WaitHandleDbConnectionPool.cs:918

  • The PendingGetConnection DueTime is still computed from CreationTimeout/ADP.TimerCurrent rather than the passed-in TimeoutTimer. For async opens this can schedule pending work beyond the caller’s remaining budget. Consider setting DueTime based on the TimeoutTimer (e.g., its ExpirationTicks or remaining duration) so WaitForPendingOpen computes delays that respect the overall timeout.
            var pendingGetConnection =
                new PendingGetConnection(
                    CreationTimeout == 0 ? Timeout.Infinite : ADP.TimerCurrent() + ADP.TimerFromSeconds(CreationTimeout / 1000),
                    owningObject,
                    taskCompletionSource,

apoorvdeshmukh
apoorvdeshmukh previously approved these changes May 27, 2026

@apoorvdeshmukh apoorvdeshmukh 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.

LGTM! Just wondering if we should create a separate issue to add any additional event tracing for scenarios where we throw exceptions to identify what caused it in the first place, but this is beyond the scope of this PR.

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
Comment thread src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj Outdated
@github-project-automation github-project-automation Bot moved this from To triage to Waiting for customer in SqlClient Board May 28, 2026
Copilot AI review requested due to automatic review settings May 28, 2026 18:57

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment thread src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.nuspec Outdated
Copilot AI review requested due to automatic review settings May 28, 2026 21:14

This comment was marked as low quality.

cheenamalhotra
cheenamalhotra previously approved these changes May 28, 2026
@mdaigle mdaigle merged commit bfbdd30 into main May 29, 2026
303 checks passed
@mdaigle mdaigle deleted the dev/mdaigle/pool-timeouts branch May 29, 2026 20:17
@github-project-automation github-project-automation Bot moved this from Waiting for customer to Done in SqlClient Board May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

8 participants