tediousjs / tedious

Node TDS module for connecting to SQL Server databases.

Home Page:http://tediousjs.github.io/tedious/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Improving timeout and cancellation behaviour

arthurschreiber opened this issue · comments

Context

tedious supports various forms of timeouts and cancellation behaviours:

  • There's a connection level connectTimeout option that allows timing out the connection attempt if the connection does not get established after a specific amount of time. Such a timeout leads to the connection attempt to fail.
  • There's a connection level requestTimeout option that allows timing out a Request execution unless the request has been fully processed after a specific amount of time. Such a timeout leads to the request being either aborted before execution has started, or to the request being aborted while it is executing on the SQL Server.
  • Individual Request objects can be cancelled at any time during sending / execution phase to a similar effect as the requestTimeout.
  • There's a connection level cancelTimeout option that aborts waiting for the request cancellation acknowledgement from the server after a request was cancelled (either due to requestTimeout or an explicit request cancellation). This leads to the connection being closed and becoming unusable.

Problem description

There's multiple problems with how these timeouts are implemented and handled. Some of this has been previously described in #1100 with a focus on connect timeout behaviour, but these problems also exist for the other timeout types and the manual request cancellation behaviour.

To fix this properly, we should align all internal APIs to build their cancellation behaviour on top of AbortSignal objects. Each asynchronous operation needs to accept a signal argument. These signal values need to be passed down correctly to all called asynchronous functions.

All calls to await need to honour AbortSignals by either using Promise.race or by passing down the signal to ensure that if the signal is aborted, all computation immediately stops.

Task Breakdown - Code Areas that need to be updated with AbortSignal support

  • StreamParser.parseTokens
  • RpcRequestPayload and other that generate the payload in a streaming fashion.
  • Connection.makeRequest
  • Connection.initialiseConnection
  • Connection.sendPreLogin
  • Connection.sendLogin7Packet
  • Connection.sendFedAuthTokenMessage
  • Connection.sendInitialSql

APIs exposed externally, like Connection.connect or Connection.execSql are out of scope of this work for now, but once all internal APIs have been wired up with AbortSignal handling, it should be trivial to expose this externally.