Struct chronicle::queue::ExcerptAppender
#[repr(C)]pub struct ExcerptAppender { /* private fields */ }
Expand description
Data written to a Queue is always appended to the end; by construction Queue does not permit data to be changed once it has been committed. For this reason we interchangeably refer to “writers” as “appenders”.
Any appends to a queue take place via an ExcerptAppender
, either using calls directly on the appender,
or (more commonly) via a scoped write DocumentContext
obtained from the appender.
Example
let queue = queue::SingleChronicleQueueBuilder::new("example").build().unwrap();
let appender = queue.acquire_appender().unwrap();
// the appender can now be used to atomically write to the queue
// either using direct writes, eg:
appender.write_slice(data);
// or via a scoped document context, eg:
{
let context = appender.scoped_writing_document();
context.wire().value_out().string("data");
}
Implementations§
§impl ExcerptAppender
impl ExcerptAppender
pub fn write_string(&self, value: &str)
pub fn write_string(&self, value: &str)
Write the given string to the queue.
The write is performed atomically, as a single message containing the provided string
§impl ExcerptAppender
impl ExcerptAppender
pub fn write_slice(&self, value: &[u8])
pub fn write_slice(&self, value: &[u8])
Write the given slice to the queue.
The write is performed atomically, as a single message containing the provided bytes
Some additional header information is added to the record by the Wire mechanism
(cf write_slice_direct
)
§impl ExcerptAppender
impl ExcerptAppender
pub fn write_slice_direct(&self, value: &[u8])
pub fn write_slice_direct(&self, value: &[u8])
Write the given slice directly to the queue.
The write is performed atomically, as a single message containing the provided bytes.
The data is memcpy’d directly into the queue, bypassing Wire which may reduce
flexibility (cf write_slice
)
§impl ExcerptAppender
impl ExcerptAppender
pub fn last_index_appended(&self) -> i64
pub fn last_index_appended(&self) -> i64
Each item written to a Queue has a unique, strictly increasing index.
This call returns the index of the last message appended to the Queue.
§impl ExcerptAppender
impl ExcerptAppender
pub fn pre_touch(&self, length: u64)
pub fn pre_touch(&self, length: u64)
In some use cases the write latency when appending data to a Queue can be reduced by “pre-touching” to prepare the Queue for a subsequent write.
Pre-touching is most effective when there is a reliable short time after each write where a latency-critical thread can do other work before the next latency-critical event is received. In such cases, using this “idle” period to pretouch the queue can reduce latency for the next write.
Example
let queue = queue::SingleChronicleQueueBuilder::new("example").build().unwrap();
let appender = queue.acquire_appender().unwrap();
// busy loop
loop {
// receive some event which generates some data to be written to the queue
// write the data to the queue
appender.write_slice_direct(data)
// use a short window to pretouch the queue to optimise handling of the next event
appender.pre_touch(MSGSIZE);
}
§impl ExcerptAppender
impl ExcerptAppender
pub fn reserve_bytes(self: Pin<&mut Self>, length: u64) -> Pin<&mut BytesWriter>
pub fn reserve_bytes(self: Pin<&mut Self>, length: u64) -> Pin<&mut BytesWriter>
Get a BytesWriter
to support direct writes to the Queue bytes - see BytesWriter
Note: this function should rarely be called directly. The recommended approach is
to use a scoped bytes writer obtained from scoped_bytes_writer
.
Example
let mut appender = queue.acquire_appender().unwrap();
let mut bytes = appender.scoped_bytes_writer(MSGSIZE);
let slice = bytes.as_mut().as_slice();
// write directly to the &mut [u8] slice
§impl ExcerptAppender
impl ExcerptAppender
pub fn scoped_writing_document(&self) -> Scoped<'_, DocumentContext>
pub fn scoped_writing_document(&self) -> Scoped<'_, DocumentContext>
Get a scoped DocumentContext
to atomically wrap a write to Queue.
Note: The Queue write lock is acquired when the scoped DocumentContext
is created, and
automatically released when the scoped context is dropped.
It is recommended to always use scoped contexts rather than opening and closing DocumentContext
s directly.
Example
let appender = queue.acquire_appender().unwrap();
{
let context = appender.scoped_writing_document();
// ...
// append data to the queue via the context
// ...
// context dropped, data formally written to the queue, and write lock released
}
pub fn write_document<F>(&self, cb: F)where
F: Fn(&Wire),
pub fn write_document<F>(&self, cb: F)where
F: Fn(&Wire),
The write_document
method uses a Wire
-based closure to conveniently apply
a sequence of steps which will be committed atomically to the queue when the closure completes.
An example use case for this is writing self-describing content to a queue in
a completely flexible format (eg to remove constraints on userdata schema changes). The below
uses two closures, the first is the closure passed to write_document
itself, the second
uses the marshallable
interface from the
ValueOut
wrapped by the closure’s `Wire’.
Example
let appender = queue.acquire_appender().unwrap();
{
appender.write_document(|wire|{
wire.write("trade").marshallable(|w|{
w.write("symbol").string("EURUSD")
.write("price").float64(1.234)
.write("quantity").float64(15e6)
// ...
});
});
}
pub fn write_bytes<F>(&self, cb: F)where
F: Fn(&Bytes),
pub fn write_bytes<F>(&self, cb: F)where
F: Fn(&Bytes),
Similarly to write_document
, the write_bytes
method
uses a Bytes
-based closure to conveniently apply a sequence of writes which
will be committed atomically to the queue when the close completes.
The message bytes are written directly using the Bytes
abstraction, and bypassing Wire
.
Example
let appender = queue.acquire_appender().unwrap();
{
appender.write_bytes(|b|{
b.write_i8(123)
.write_f32(4.56)
.write_string("data");
});
}
pub fn write_bytes_slice(&self, bytes: &Bytes)
pub fn write_bytes_slice(&self, bytes: &Bytes)
Writes the available content from the given Bytes
instance
to the queue