microsoft / microsoft/mssql-python

FEAT: Built-in configurable connection and transient-fault retry logic

Ouverte
#682 5 commentaires 0 réactions 1 personne assignée Voir sur GitHub

@Om-singhaI y travaille déjà.

Depuis le 2/9/2026.

discussion enhancement good first issue inADO triage done up for grabs 🙌
Langage dominant
Python
Étoiles
473
Forks
60
Merge moyen
2 j 11 h
PR mergées (30 j)
36

Description

Summary

Add first-class, configurable retry logic to mssql-python so applications get transient-fault resiliency without hand-rolling their own retry loops. Today the only retry surface is the ODBC-level ConnectRetryCount/ConnectRetryInterval keywords, which only silently reconnect a dropped idle connection. They do not retry a connect() that fails transiently, nor a query that fails with a recoverable error (deadlock victim, lock/query timeout, or Azure SQL throttling such as 40197/40501/49918). Every app has to reimplement this, and most get the backoff, jitter, and "which errors are retriable" classification subtly wrong.

Motivation
  • Parity with the .NET Microsoft.Data.SqlClient configurable retry providers (SqlRetryLogicBaseProvider, SqlConnection.RetryLogicProvider / SqlCommand.RetryLogicProvider) and the Azure SDK retry-policy conventions.
  • Azure SQL Database and SQL Managed Instance routinely surface transient errors during failover, scaling, and throttling; robust handling is effectively required for production.
  • Reduces copy-pasted, error-prone retry loops and centralizes the transient-error taxonomy in the driver where it can be maintained authoritatively.
Proposed API (for discussion)

A retry policy object, attachable at the connection level and overridable per cursor/execute:

from mssql_python import RetryPolicy, connect

policy = RetryPolicy(
    max_attempts=3,           # total tries, not extra retries
    backoff="exponential",    # "exponential" | "fixed" | "none"
    base_delay=1.0,           # seconds
    max_delay=30.0,           # cap per wait
    jitter=True,              # full jitter to avoid thundering herd
    # Retriable classification, defaulted by the driver but overridable:
    # connect-scope errors -> fresh connection; query-scope -> same connection
)

conn = connect(conn_str, retry_policy=policy)      # applies to connect() + queries
cursor = conn.cursor(retry_policy=policy)          # optional override
cursor.execute(sql, *params, retry_policy=policy)  # optional per-call override

Key behaviors:

  • Two scopes, because recovery differs: connection-establishment/connection-loss errors need a fresh connection; connection-surviving errors (deadlock, query timeout, throttling) retry on the same connection.
  • Driver-maintained default retriable set (transient SQLSTATEs / native error numbers), overridable by the caller.
  • Idempotency guardrail: by default only retry statements the caller marks safe, or document clearly that writes must be wrapped in an explicit transaction. Never silently replay a non-idempotent write.
  • Observability: emit standard logging records on each retry (attempt count, error, delay) and on final give-up.
  • No behavior change by default (opt-in), so existing code is unaffected.
Alternatives considered
  • ODBC ConnectRetryCount/ConnectRetryInterval — only covers idle-connection reconnect, not connect() or query retries.
  • Application-level helper loops — what everyone does now; duplicative and easy to get wrong (backoff, jitter, error classification, connect-vs-query scope).
Additional context

Docs currently ship a sample connect_with_retry / execute_with_retry pattern that demonstrates exactly this behavior and would map cleanly onto a built-in RetryPolicy.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.