Expand description

Fast Ingestion of data into QuestDB

The ingress module implements QuestDB’s variant of the InfluxDB Line Protocol (ILP) over TCP.

To get started:

  • Connect to QuestDB by creating a Sender object.
  • Populate a Buffer with one or more rows of data.
  • Send the buffer via the Sender’s flush method.
use questdb::{
    Result,
    ingress::{
        Sender,
        Buffer,
        SenderBuilder}};
 
fn main() -> Result<()> {
   let mut sender = SenderBuilder::new("localhost", 9009).connect()?;
   let mut buffer = Buffer::new();
   buffer
       .table("sensors")?
       .symbol("id", "toronto1")?
       .column_f64("temperature", 20.0)?
       .column_i64("humidity", 50)?
       .at_now()?;
   sender.flush(&mut buffer)?;
   Ok(())
}

Flushing

The Sender’s flush method will clear the buffer which is then reusable for another batch of rows.

Dropping the sender will close the connection to QuestDB and any unflushed messages will be lost: In other words, do not forget to flush before closing the connection!

A common technique is to flush periodically on a timer and/or once the buffer exceeds a certain size. You can check the buffer’s size by the calling Buffer’s len method.

Note that flushing will automatically clear the buffer’s contents. If you’d rather preserve the contents (for example, to send the same data to multiple QuestDB instances), you can call flush_and_keep instead.

Connection Security Options

To establish an authenticated and TLS-encrypted connection, call the SenderBuilder’s auth and tls methods.

Here’s an example that uses full security:

use questdb::ingress::{SenderBuilder, Tls, CertificateAuthority};
 
// See: https://questdb.io/docs/reference/api/ilp/authenticate
let mut sender = SenderBuilder::new("localhost", 9009)
    .auth(
        "testUser1",                                    // kid
        "5UjEMuA0Pj5pjK8a-fa24dyIf-Es5mYny3oE_Wmus48",  // d
        "fLKYEaoEb9lrn3nkwLDA-M_xnuFOdSt9y0Z7_vWSHLU",  // x
        "Dt5tbS1dEDMSYfym3fgMv0B99szno-dFc1rYF9t0aac")  // y
    .tls(Tls::Enabled(CertificateAuthority::WebpkiRoots))
    .connect()?;

Note that as of writing QuestDB does not natively support TLS encryption. To use TLS use a TLS proxy such as HAProxy.

For testing, you can use a self-signed certificate and key.

See our notes on how to generate keys that this library will accept.

From the API, you can then point to a custom CA file:

use std::path::PathBuf;
use questdb::ingress::{SenderBuilder, Tls, CertificateAuthority};
 
let mut sender = SenderBuilder::new("localhost", 9009)
    .tls(Tls::Enabled(CertificateAuthority::File(
        PathBuf::from("/path/to/server_rootCA.pem"))))
    .connect()?;

Avoiding revalidating names

To avoid re-validating table and column names, consider re-using them across rows.

use questdb::ingress::{
    TableName,
    ColumnName,
    Buffer};
 
let mut buffer = Buffer::new();
let tide_name = TableName::new("tide")?;
let water_level_name = ColumnName::new("water_level")?;
buffer.table(tide_name)?.column_f64(water_level_name, 20.4)?.at_now()?;
buffer.table(tide_name)?.column_f64(water_level_name, 17.2)?.at_now()?;

Buffer API sequential coupling

Symbols must always be written before rows. See the Buffer documentation for details. Each row must be terminated with a call to either at or at_now.

Data quality and threading considerations

Troubleshooting Common Issues

Production-optimized QuestDB configuration

If you can’t initially see your data through a select SQL query straight away, this is normal: by default the database will only commit data it receives though the line protocol periodically to maximize throughput.

For dev/testing you may want to tune the following database configuration parameters as so in server.conf:

cairo.max.uncommitted.rows=1
line.tcp.maintenance.job.interval=100

Infrequent Flushing

You may not see data appear in a timely manner because you’re not calling the flush method often enough.

Debugging disconnects and inspecting errors

The ILP protocol does not send errors back to the client. Instead, on error, the QuestDB server will disconnect and any error messages will be present in the server logs.

If you want to inspect or log a buffer’s contents before it is sent, you can call its as_str method.

Structs

A reusable buffer to prepare ILP messages.

A validated column name.

Connects to a QuestDB instance and inserts data via the ILP protocol.

Accumulate parameters for a new Sender instance.

A u16 port number or String port service name as is registered with /etc/services or equivalent.

A validated table name.

A i64 timestamp expressed as microseconds since the UNIX epoch (UTC).

A i64 timestamp expressed as nanoseconds since the UNIX epoch (UTC).

Enums

Root used to determine how to validate the server’s TLS certificate.

Options for full-connection encryption via TLS.