Skip to main content

Log

Struct Log 

Source
pub struct Log { /* private fields */ }
Expand description

Caller-owned heap history with fixed limits and monotonic append watermarks.

Implementations§

Source§

impl Log

Source

pub const fn new(limits: Limits) -> Self

Construct an empty log without preallocating the configured maximum.

Examples found in repository?
examples/worker.rs (lines 7-11)
6fn main() {
7    let mut log = Log::new(Limits {
8        max_entries: NonZeroUsize::new(8).expect("positive capacity"),
9        max_message_bytes: 32,
10        max_label_bytes: 16,
11    });
12    for (created_at_secs, level, message) in [
13        (10, Level::Info, "delivery accepted"),
14        (
15            11,
16            Level::Warn,
17            "provider reply is still unknown; reconcile before retry",
18        ),
19        (12, Level::Ok, "original delivery reconciled"),
20    ] {
21        log.append(EntryInput {
22            created_at_secs,
23            level,
24            source: "worker",
25            topic: Some("delivery"),
26            message,
27        })
28        .expect("valid bounded entry");
29    }
30    let page = log.page(
31        Filter::default(),
32        PageRequest {
33            before: None,
34            max_results: NonZeroUsize::new(8).expect("positive results"),
35            max_scanned: NonZeroUsize::new(8).expect("positive scan"),
36        },
37    );
38    for entry in page.entries {
39        println!("{} {:?}: {}", entry.sequence, entry.level, entry.message);
40    }
41    let batch = log.prune_expired(16, 5, 1);
42    assert_eq!(batch.removed, 1);
43    assert_eq!(log.next_expiry_secs(5), Some(17));
44}
Source

pub fn len(&self) -> usize

Return the retained row count.

Source

pub fn is_empty(&self) -> bool

Whether this log currently has no retained rows.

Source

pub fn append(&mut self, input: EntryInput<'_>) -> Result<u64, AppendError>

Admit one row and evict the oldest if the count ceiling is reached.

§Errors

Returns a typed refusal for oversized labels, regressed time or exhausted sequence identities. Validation completes before any eviction or mutation.

Examples found in repository?
examples/worker.rs (lines 21-27)
6fn main() {
7    let mut log = Log::new(Limits {
8        max_entries: NonZeroUsize::new(8).expect("positive capacity"),
9        max_message_bytes: 32,
10        max_label_bytes: 16,
11    });
12    for (created_at_secs, level, message) in [
13        (10, Level::Info, "delivery accepted"),
14        (
15            11,
16            Level::Warn,
17            "provider reply is still unknown; reconcile before retry",
18        ),
19        (12, Level::Ok, "original delivery reconciled"),
20    ] {
21        log.append(EntryInput {
22            created_at_secs,
23            level,
24            source: "worker",
25            topic: Some("delivery"),
26            message,
27        })
28        .expect("valid bounded entry");
29    }
30    let page = log.page(
31        Filter::default(),
32        PageRequest {
33            before: None,
34            max_results: NonZeroUsize::new(8).expect("positive results"),
35            max_scanned: NonZeroUsize::new(8).expect("positive scan"),
36        },
37    );
38    for entry in page.entries {
39        println!("{} {:?}: {}", entry.sequence, entry.level, entry.message);
40    }
41    let batch = log.prune_expired(16, 5, 1);
42    assert_eq!(batch.removed, 1);
43    assert_eq!(log.next_expiry_secs(5), Some(17));
44}
Source

pub fn prune_expired( &mut self, now_secs: u64, max_age_secs: u64, max_remove: usize, ) -> RetentionBatch

Remove at most max_remove entries strictly older than the age cutoff. An entry remains available through its full configured age second.

Examples found in repository?
examples/worker.rs (line 41)
6fn main() {
7    let mut log = Log::new(Limits {
8        max_entries: NonZeroUsize::new(8).expect("positive capacity"),
9        max_message_bytes: 32,
10        max_label_bytes: 16,
11    });
12    for (created_at_secs, level, message) in [
13        (10, Level::Info, "delivery accepted"),
14        (
15            11,
16            Level::Warn,
17            "provider reply is still unknown; reconcile before retry",
18        ),
19        (12, Level::Ok, "original delivery reconciled"),
20    ] {
21        log.append(EntryInput {
22            created_at_secs,
23            level,
24            source: "worker",
25            topic: Some("delivery"),
26            message,
27        })
28        .expect("valid bounded entry");
29    }
30    let page = log.page(
31        Filter::default(),
32        PageRequest {
33            before: None,
34            max_results: NonZeroUsize::new(8).expect("positive results"),
35            max_scanned: NonZeroUsize::new(8).expect("positive scan"),
36        },
37    );
38    for entry in page.entries {
39        println!("{} {:?}: {}", entry.sequence, entry.level, entry.message);
40    }
41    let batch = log.prune_expired(16, 5, 1);
42    assert_eq!(batch.removed, 1);
43    assert_eq!(log.next_expiry_secs(5), Some(17));
44}
Source

pub fn next_expiry_secs(&self, max_age_secs: u64) -> Option<u64>

First second at which the oldest row expires; None for empty history or overflow.

Examples found in repository?
examples/worker.rs (line 43)
6fn main() {
7    let mut log = Log::new(Limits {
8        max_entries: NonZeroUsize::new(8).expect("positive capacity"),
9        max_message_bytes: 32,
10        max_label_bytes: 16,
11    });
12    for (created_at_secs, level, message) in [
13        (10, Level::Info, "delivery accepted"),
14        (
15            11,
16            Level::Warn,
17            "provider reply is still unknown; reconcile before retry",
18        ),
19        (12, Level::Ok, "original delivery reconciled"),
20    ] {
21        log.append(EntryInput {
22            created_at_secs,
23            level,
24            source: "worker",
25            topic: Some("delivery"),
26            message,
27        })
28        .expect("valid bounded entry");
29    }
30    let page = log.page(
31        Filter::default(),
32        PageRequest {
33            before: None,
34            max_results: NonZeroUsize::new(8).expect("positive results"),
35            max_scanned: NonZeroUsize::new(8).expect("positive scan"),
36        },
37    );
38    for entry in page.entries {
39        println!("{} {:?}: {}", entry.sequence, entry.level, entry.message);
40    }
41    let batch = log.prune_expired(16, 5, 1);
42    assert_eq!(batch.removed, 1);
43    assert_eq!(log.next_expiry_secs(5), Some(17));
44}
Source

pub fn page(&self, filter: Filter<'_>, request: PageRequest) -> Page<'_>

Scan newest-first without cloning retained messages or counting every match. Follow next_before with the same filters, including after an empty page.

Examples found in repository?
examples/worker.rs (lines 30-37)
6fn main() {
7    let mut log = Log::new(Limits {
8        max_entries: NonZeroUsize::new(8).expect("positive capacity"),
9        max_message_bytes: 32,
10        max_label_bytes: 16,
11    });
12    for (created_at_secs, level, message) in [
13        (10, Level::Info, "delivery accepted"),
14        (
15            11,
16            Level::Warn,
17            "provider reply is still unknown; reconcile before retry",
18        ),
19        (12, Level::Ok, "original delivery reconciled"),
20    ] {
21        log.append(EntryInput {
22            created_at_secs,
23            level,
24            source: "worker",
25            topic: Some("delivery"),
26            message,
27        })
28        .expect("valid bounded entry");
29    }
30    let page = log.page(
31        Filter::default(),
32        PageRequest {
33            before: None,
34            max_results: NonZeroUsize::new(8).expect("positive results"),
35            max_scanned: NonZeroUsize::new(8).expect("positive scan"),
36        },
37    );
38    for entry in page.entries {
39        println!("{} {:?}: {}", entry.sequence, entry.level, entry.message);
40    }
41    let batch = log.prune_expired(16, 5, 1);
42    assert_eq!(batch.removed, 1);
43    assert_eq!(log.next_expiry_secs(5), Some(17));
44}

Trait Implementations§

Source§

impl Debug for Log

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Log

§

impl RefUnwindSafe for Log

§

impl Send for Log

§

impl Sync for Log

§

impl Unpin for Log

§

impl UnsafeUnpin for Log

§

impl UnwindSafe for Log

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.