Skip to content

Connections and TLS ​

A connection is a Q object that owns at most one socket to one q process. Python and Node.js accept the same settings under slightly different names:

SettingPython xqdb.Q(...)Node.js QOptionsDefault
HosthosthostRequired. Empty means 127.0.0.1.
PortportportRequired. Node.js checks for an integer from 1 to 65535.
Usernameuseruser""
Passwordpasswdpassword""
TLSenable_tlstlsOff
Socket timeouttimeout, whole seconds, 0 for nonetimeout, millisecondsPython 0, Node.js 30_000
Retriesretriesretries0
Invalid UTF-8 textsymbol_encodingsymbolEncoding"strict"
DataFrame backendbackendNot applicable"pyarrow"

timeout and retries behave differently in the two bindings. See Timeouts and Retries. symbol_encoding is covered in Values, Nulls, and Text.

python
import xqdb

conn = xqdb.Q(
    "q.example.com",
    5001,
    user="analyst",
    passwd="secret",
    enable_tls=True,
    timeout=30,
)
ts
import { Q } from "@xbbg/xqdb";

const q = await Q.connect({
  host: "q.example.com",
  port: 5001,
  user: "analyst",
  password: "secret",
  tls: true,
  timeout: 30_000,
});
await q.disconnect();

Lifecycle ​

ActionPythonNode.js
CreateQ(...) stores the settings and opens no socket.new Q(options) validates options and throws RangeError if one is invalid. It opens no socket.
Connectconn.connect(). Does nothing if already connected.await q.connect(), or await Q.connect(options) to create and connect in one step.
Querysync() and asyn() connect automatically when no socket is open.sync() and asyn() connect automatically when no socket is open.
Receivereceive() does not open a socket. Without one it raises XqdbIOError("Not Connected."). With retries set, a failed receive() reconnects before it retries.receive() does not open a socket. Without one it rejects with XQDB_IO.
Disconnectconn.disconnect() raises XqdbIOError if no socket is open.await q.disconnect() can be called any number of times. The same Q can connect again afterwards.

After an I/O error, including a timeout, xqdb closes the socket. The next sync() or asyn() opens a new one. Server-side state tied to the old connection is gone, for example a tickerplant subscription.

A Python Q is not a context manager. Close it in finally, and guard disconnect() if the socket may already be closed:

python
import xqdb

conn = xqdb.Q("localhost", 1800)
try:
    print(conn.sync("1+1"))
finally:
    try:
        conn.disconnect()
    except xqdb.XqdbIOError:
        pass  # already disconnected, for example after an I/O error

In Node.js, call disconnect() in finally and do not rely on garbage collection. A collected Q does close its socket and stop its worker thread, but only whenever the garbage collector gets to it.

Local hosts ​

In both bindings an empty host means 127.0.0.1. Python also replaces a host equal to this machine's own hostname (socket.gethostname()) with 127.0.0.1. Keep this in mind with TLS, because the certificate is then checked against 127.0.0.1.

Authentication ​

During the q handshake, xqdb sends user:password. It requests IPC capability 6 and accepts any capability of 1 or higher in the reply. q rejects bad credentials by closing the connection. xqdb reports that as XqdbAuthError, with code XQDB_AUTH in Node.js and the message Wrong credential. Authentication failures are never retried.

Credentials travel in clear text without TLS

q IPC authentication sends the username and password unencrypted. Enable TLS for any connection that carries credentials, unless another trusted transport such as a VPN or SSH tunnel already protects the socket.

TLS ​

Set enable_tls=True (Python) or tls: true (Node.js) when the q process listens with TLS enabled. xqdb uses rustls with TLS 1.2 or 1.3 and verifies:

  • the certificate chain, against the operating system's trust store, and
  • the host you connected to, which must match a DNS name or IP address in the certificate.

An untrusted, expired, or mismatched certificate fails the connection. The handshake failure is reported as an I/O error, XqdbIOError in Python or XQDB_IO in Node.js, for example invalid peer certificate: UnknownIssuer. Because it is an I/O error, retries repeats the attempt. With TLS enabled, Node.js also requires host to be a valid DNS name or IP address.

Release 0.1.8 has no options for TLS beyond on and off:

  • Custom certificate authorities. There is no CA file option. If your q servers use a private CA, add it to the operating system's trust store (the Windows certificate store, the macOS keychain, or the system CA bundle on Linux).
  • Client certificates. xqdb presents no client certificate, so q servers that require mutual TLS reject it.
  • Disabling verification. Certificate and hostname checks cannot be turned off.

Threads and concurrency ​

  • Python. One Q serves one thread at a time. xqdb releases the GIL during network I/O and decoding, so other threads keep running during a query. A second thread that calls the same Q while a call is in progress gets RuntimeError: Already borrowed. Give each thread its own Q.
  • Node.js. Calls on one Q run in order on that connection's native worker thread and never block the event loop. A Q accepts one running command plus eight waiting commands, then rejects new calls with XQDB_BACKPRESSURE. Open several Q objects to run requests in parallel. See Node.js Workers and Backpressure.

In both bindings, keep subscriptions on their own connection. sync() reads the next message on the socket, and on a subscribed connection that can be a pushed update instead of the reply. See Queries and Subscriptions.

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