Skip to content

Checkout liveness: use TinyTDS #ping from active? (follow-up to #1396) #1413

Description

@emailrhoads

Summary

Idle TCP RST (TCP reset: peer or middlebox abruptly closes the socket while the client still believes the session is alive) leaves FreeTDS dbdead / TinyTDS active? stale-true until the next real I/O. Rails 8 verify! then hands out a half-dead checkout. The next statement can hang for the connection’s full FreeTDS statement timeout (often minutes) before failing with something like Adaptive Server connection timed out.

This is the checkout-liveness half of #1396. Exception mapping (DBPROCESS is dead…ConnectionNotEstablished) was addressed in #1397 / 8.0.11; detecting the dead handle before the real query still needs a bounded round-trip.

Rails / adapter context

  • Postgres and Trilogy still probe in active? today (query ";" / #ping).
  • This adapter used to run raw_connection_do "SELECT 1" in active? until #1121 (Oct 2023) switched to passive TinyTDS active?.
  • A naive return to SELECT 1 would restore probing but hang on the connection’s multi-minute FreeTDS timeout when the socket is already dead. The probe needs a short FreeTDS DBSETTIME, not Ruby Timeout (which does not reliably interrupt TinyTDS/C I/O).

Proposed split

Layer Responsibility PR
tiny_tds Driver primitive: Client#ping(timeout:) + query_timeout= (temporary short DBSETTIME, SELECT 1, restore on success; false on failure) rails-sqlserver/tiny_tds#609
activerecord-sqlserver-adapter Policy: call #ping from active? when available; :ping_timeout (default 2s, 0 disables); fallback to passive active? on older TinyTDS rails-sqlserver/activerecord-sqlserver-adapter#1412

Ask for maintainers

Please take a look at both PRs. tiny_tds appears lightly maintained right now, and without a reviewed #ping (or equivalent) the adapter cannot match Postgres/Trilogy checkout behavior without reintroducing long hangs. Adapter #1412 is ready to consume #ping once tiny_tds#609 lands (or guidance on an alternate driver API).

Happy to adjust either PR based on preferred defaults, naming, or whether ping should live only behind verify! vs every active?.

Related

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions