2.0.0
What's Changed
This is a major release with new features and breaking changes.
Features
-
Support for ILP over HTTP. The sender can now send data to QuestDB via HTTP instead of TCP. This provides error feedback from the server and new features.
conf = 'http::addr=localhost:9000;' with Sender.from_conf(conf) as sender: sender.row(...) sender.dataframe(...) # Will raise `IngressError` if there is an error from the server. sender.flush()
-
New configuration string construction. The sender can now be also constructed from a configuration string in addition to the constructor arguments. This allows for more flexible configuration and is the recommended way to construct a sender. The same string can also be loaded from the
QDB_CLIENT_CONF
environment variable. The constructor arguments have been updated and some options have changed. -
Explicit transaction support over HTTP. A set of rows for a single table can now be committed via the sender transactionally. You can do this using a
with sender.transaction('table_name') as txn:
block.conf = 'http::addr=localhost:9000;' with Sender.from_conf(conf) as sender: with sender.transaction('test_table') as txn: # Same arguments as the sender methods, minus the table name. txn.row(...) txn.dataframe(...)
-
A number of documentation improvements.
Breaking Changes
-
New
protocol
parameter in the Sender constructor. In the previous version, the protocol was always TCP. In this new version, you must specify the protocol explicitly. -
New auto-flush defaults. In previous versions, auto-flushing was enabled by default and triggered by a maximum buffer size. In this new version, auto-flushing is enabled by row count (600 rows by default) and interval (1 second by default), while auto-flushing by buffer size is disabled by default.
The old behavior can still be achieved by tweaking the auto-flush settings.
Setting Old default New default auto_flush_rows off 600 auto_flush_interval off 1000 auto_flush_bytes 64512 off -
The
at=..
argument of therow
anddataframe
methods is now mandatory. Omitting it would previously use a server-generated timestamp for the row. Now, if you want a server-generated timestamp, you can pass theServerTimestamp
singleton to this parameter. TheServerTimestamp
behavior is considered legacy. -
The
auth=(u, t, x, y)
argument of theSender
constructor has now been broken up into multiple arguments:username
,token
,token_x
,token_y
. -
The
tls
argument of theSender
constructor has been removed and replaced with theprotocol
argument. UseProtocol.Tcps
(orProtocol.Https
) to enable TLS. Thetls
values have been moved to newtls_ca
andtls_roots
configuration settings. -
The
net_interface
argument of theSender
constructor has been renamed tobind_interface
and is now only available for TCP connections.
The following example shows how to migrate to the new API.
Old questdb 1.x code
from questdb.ingress import Sender
auth = (
'testUser1',
'5UjEMuA0Pj5pjK8a-fa24dyIf-Es5mYny3oE_Wmus48',
'token_x=fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU',
'token_y=Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac')
with Sender('localhost', 9009, auth=auth, tls=True) as sender:
sender.row(
'test_table',
symbols={'sym': 'AAPL'},
columns={'price': 100.0}) # `at=None` was defaulted for server time
Equivalent questdb 2.x code
from questdb.ingress import Sender, Protocol, ServerTimestamp
sender = Sender(
Protocol.Tcps,
'localhost',
9009,
username='testUser1',
token='5UjEMuA0Pj5pjK8a-fa24dyIf-Es5mYny3oE_Wmus48',
token_x='token_x=fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU',
token_y='token_y=Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac',
auto_flush_rows='off',
auto_flush_interval='off',
auto_flush_bytes=64512)
with sender:
sender.row(
'test_table',
symbols={'sym': 'AAPL'},
columns={'price': 100.0},
at=ServerTimestamp)
Equivalent questdb 2.x code with configuration string
from questdb.ingress import Sender, ServerTimestamp
conf = (
'tcp::addr=localhost:9009;' +
'username=testUser1;' +
'token=5UjEMuA0Pj5pjK8a-fa24dyIf-Es5mYny3oE_Wmus48;' +
'token_x=token_x=fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU;' +
'token_y=token_y=Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac;' +
'auto_flush_rows=off;' +
'auto_flush_interval=off;' +
'auto_flush_bytes=64512;')
with Sender.from_conf(conf) as sender:
sender.row(
'test_table',
symbols={'sym': 'AAPL'},
columns={'price': 100.0},
at=ServerTimestamp)