#[repr(C)]
pub struct SingleChronicleQueueBuilder { /* private fields */ }
Expand description

The SingleChronicleQueueBuilder is a convenience type used to assemble a SingleChronicleQueue handle.

The builder supports a number of calls to configure the Queue, with each call returning a handle to self in order to faciltate chaining for syntactic convenience.

The final call to the builder should be build(), which creates and returns the SingleChronicleQueue Result handle.

Example

let queue = queue::SingleChronicleQueueBuilder::new("example")
                .blocksize(256i64 << 20)
                .store_file_listener(MyListener{})
                .timeout_ms(10000)
                .rollcycle(queue::RollCycle::HalfHourly)
                .build()
                .unwrap();

Implementations§

Chronicle Queue content is backed by memory mapped files, and Queue maps a series of segments on demand rather than attempting to map the whole file at once. The blocksize configures the size of each individually mapped segment (in bytes).

Memory mapping a new segment is a relatively expensive operation, so larger segment sizes are generally favoured in order to keep mapping reasonably infrequent. That said, very large segments can put pressure on memory resources. A blocksize of around 256MB is generally a good compromise, although for systems with large amounts of memory multi-GB segments can be a sensible choice in some cases.

Note: The largest singe message which is guaranteed to be written to a segment is 25% of the segment size. This is rarely a practical issue, but where very large individual messages are written to a Queue, the blocksize should be at least 4x the largest expected message size

Arguments
  • blocksize: the blocksize in bytes. Default is 64MB

Chronicle Queue backing files can be regularly rolled to assist with data organisation and also to avoid any single file becoming excessively large.

Note: file rolling is a relatively expensive operation. To minimise jitter impact it is recommended to roll a file no more frequently than once every 1,000,000 messages where practical.

In addition to this, each Queue maintains an index to help quickly locate items when repositioning tailers for example. Indexes broadly work via a jump + linear scan to locate specific content, and this works best with more granular jumps and correspondingly shorter linear scans. The index structure is fixed for a particular RollCycle so determining the best RollCycle for a given use case depends on a combination of:

  • Data rate
  • Maximum preferred file size
  • Frequency of rolling
  • Index structure

As a general rule of thumb it is recommended to start with a FastDaily roll cycle, and adapt as necessary if benchmarking highlights any issue related to rolling.

See RollCycle for more information

When writing data to a Queue, the writer DocumentContext must first acquire a write lock. If a lock cannot be acquired in a resonable time then the pending writer can forcibly acquire the lock.

In this situation, what counts as a “reasonable” time will depend on the context in which the queue is being used. Generally, write operations using Queue are measured in fractions of a microsecond, so if a pending writer is unable to acquire a write lock within a couple of orders of magnitude of this then something is likely amiss and it will be appropriate to forcibly acquire the lock.

The default timeout value is 10000ms. For historical reasons the actual time used internally is 1.5x the value passed to this function, making the default timeout 15s.

Create the Queue handle according to the configuration provided in the other SingleChronicleQueueBuilder calls.

Once build() has been called the SingleChronicleQueueBuilder instance should be discarded.

The recommended aproach is to combine the configuration and build within a single chained call, for example:

let queue = queue::SingleChronicleQueueBuilder::new("example")
                .blocksize(256i64 << 20)
                .store_file_listener(MyListener{})
                .timeout_ms(10000)
                .build()
                .unwrap();

Create a SingleChronicleQueue handle corresponding to the given path.

The Queue is opened, or created if it doesn’t already exist

Arguments
  • path: &str The file path corresponding to the directory which will hold the internal queue files
Example
let queue = queue::SingleChronicleQueueBuilder::new("/path/to/queue")
                .blocksize(256i64 << 20)
                .build()
                .unwrap();

The StoreFileListener trait supports two callbacks on_acquired and on_released which are called each time a new memory-mapped queue cycle is acquired or released respectively.

A bespoke derivation from StoreFileListener should be provided where required, and is then attached to the queue during the initial builder stage using store_file_listener.

Full details on the various RollCycles supported by Queue are given here

Example
use chronicle:*;

#[derive(Default)]
struct ExampleListener {}
impl chronicle::StoreFileListener for ExampleListener {
  fn on_acquired(&self, cycle: i32) {
        println!("on_acquired callback, cycle = {}", cycle);
    }
    fn on_released(&self, cycle: i32)  {
        println!("on_released callback, cycle = {}", cycle);
    }
}

let queue = queue::SingleChronicleQueueBuilder::new("Example")
    .store_file_listener(ExampleListener{})
    .build()
    .unwrap();

Trait Implementations§

§

type Id

A type-level representation of the type’s C++ namespace and type name. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.