Skip to content

Timeouts and Retries ​

timeout and retries use the same names in both bindings but do different things. Read the section for your binding before turning either on.

Timeouts ​

PythonNode.js
UnitWhole seconds (int)Milliseconds, rounded up to whole seconds
Default0, which means no timeout30_000 (30 seconds)
Allowed range0 or moreMore than 0 and at most 86_400_000 (24 hours). Other values throw RangeError.

xqdb applies the timeout in two places:

  1. Connecting. It is the total budget for TCP connection attempts across every address the host name resolves to.
  2. Each socket read and write. A read that waits longer than the timeout fails. This includes waiting for a query result, so a q query that runs longer than the timeout before replying fails even though the server is healthy.

When a timeout fires, the call fails with an I/O error (XqdbIOError, or code XQDB_IO in Node.js), and xqdb closes the socket. The next sync() or asyn() opens a new connection. receive() does not, so call connect() and subscribe again first.

Node.js defaults to 30 seconds

Any Node.js request whose reply takes more than 30 seconds to arrive fails with XQDB_IO unless you raise timeout. Set it above your slowest expected query, up to 24 hours. Subscription connections need it above the longest quiet period of the feed.

Python defaults to no timeout

With timeout=0, a call can block its thread indefinitely if the server or the network stops responding. Set a timeout for request/response connections. A subscription connection that waits on a quiet feed can keep 0.

Retries in Python ​

retries wraps sync(), asyn(), and receive(). It does not wrap connect(). Only XqdbIOError triggers a retry. Authentication failures, q errors, and conversion errors are raised immediately.

With retries=N greater than 0, xqdb makes at most N attempts in total. After failed attempt k (counting from 0) it sleeps 2k seconds, and it also sleeps after the final failure before raising it:

retriesAttemptsSleep before the error is raised
0 (default)1none
111 s
221 s + 2 s = 3 s
331 s + 2 s + 4 s = 7 s

Each retry logs an INFO message through Python's root logging logger.

A retried request is sent again

On each retry, xqdb opens a new connection and sends the same request again. If the first attempt failed after q had already received it, for example because the connection dropped while q was running the query, q runs the request twice. Use retries only for requests that are safe to repeat, such as reads. For inserts, upserts, and other side effects, keep retries=0 and handle XqdbIOError yourself.

receive() retries reconnect before sleeping, and the new connection has no subscription. If that reconnect fails, its error is raised straight away. For feeds, keep retries=0 and resubscribe explicitly, as shown in Queries and Subscriptions.

To retry only reads, write the loop yourself:

python
import time

import xqdb

conn = xqdb.Q("localhost", 1800, timeout=30)


def read(query: str, attempts: int = 3):
    for attempt in range(attempts):
        try:
            return conn.sync(query)
        except xqdb.XqdbIOError:
            if attempt == attempts - 1:
                raise
            time.sleep(2**attempt)


trades = read("select from trade where date=.z.d")

Retries in Node.js ​

retries applies only to explicit connect() calls, including the one inside Q.connect(options):

  • retries: N allows up to N more connection attempts after the first one fails.
  • Attempts follow each other immediately, with no delay.
  • Only XQDB_IO failures are retried. TLS handshake failures count as XQDB_IO. Authentication failures (XQDB_AUTH) are not retried.
  • Queries are never retried or re-sent. When sync() or asyn() connects automatically, it makes one attempt.

To wait between attempts, call connect() in your own loop with a delay.

Cancelling a call ​

Release 0.1.8 has no cancellation API. Use timeout to bound how long a call can wait.

  • Python. sync(), asyn(), and receive() block the calling thread until they finish, fail, or time out.
  • Node.js. A pending promise cannot be cancelled. disconnect() is queued behind commands already running on that connection, so a disconnect() issued during a pending receive() resolves only after the receive() gets a message or times out. Size timeout so that this wait is acceptable.

xbbg is independent open-source software and is not affiliated with, endorsed by, sponsored by, or approved by Bloomberg Finance L.P.