pub struct Log { /* private fields */ }Expand description
Caller-owned heap history with fixed limits and monotonic append watermarks.
Implementations§
Source§impl Log
impl Log
Sourcepub const fn new(limits: Limits) -> Self
pub const fn new(limits: Limits) -> Self
Construct an empty log without preallocating the configured maximum.
Examples found in repository?
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}Sourcepub const fn limits(&self) -> Limits
pub const fn limits(&self) -> Limits
Return the fixed bounds without copying retained messages.
Sourcepub fn snapshot(&self) -> LogSnapshot
pub fn snapshot(&self) -> LogSnapshot
Copy all retained rows and both append watermarks for explicit checkpointing. Work and allocation scale with retained history, not a cursor-page limit.
Sourcepub fn restore(snapshot: LogSnapshot) -> Result<Self, RestoreError>
pub fn restore(snapshot: LogSnapshot) -> Result<Self, RestoreError>
Admit a complete checkpoint without replaying entries or reissuing identities.
Empty retained history preserves its original append watermarks. Admission proves internal consistency, not source authenticity or host continuity. Byte decoders must bound allocation before constructing the checkpoint.
§Errors
Rejects bounds, row ordering, watermarks and truncation states that cannot result from this engine’s append/retention operations.
Sourcepub fn append(&mut self, input: EntryInput<'_>) -> Result<u64, AppendError>
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?
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}Sourcepub fn prune_expired(
&mut self,
now_secs: u64,
max_age_secs: u64,
max_remove: usize,
) -> RetentionBatch
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?
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}Sourcepub fn next_expiry_secs(&self, max_age_secs: u64) -> Option<u64>
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?
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}Sourcepub fn page(&self, filter: Filter<'_>, request: PageRequest) -> Page<'_>
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?
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}