///|
/// A queued delivery waiting to be processed by a scheduler.
pub(all) struct PendingDelivery {
hook_id : String
event : WebhookEvent
queued_at_ms : Int
attempts_used : Int
} derive(Eq, @debug.Debug)
///|
/// A delivery that permanently failed and was moved to the dead letter queue.
pub(all) struct DeadLetterEntry {
hook_id : String
event : WebhookEvent
reason : String
failed_at_ms : Int
attempts : Int
} derive(Eq, @debug.Debug)
///|
/// In-memory outbox. Use this as the default in tests and single-process
/// applications; a durable implementation can swap in behind the same shape.
pub struct InMemoryOutbox {
entries : Array[PendingDelivery]
} derive(@debug.Debug)
///|
pub fn InMemoryOutbox::new() -> InMemoryOutbox {
{ entries: [], }
}
///|
pub fn InMemoryOutbox::enqueue(
self : InMemoryOutbox,
hook_id : String,
event : WebhookEvent,
now_ms : Int,
) -> Unit {
self.entries.push({ hook_id, event, queued_at_ms: now_ms, attempts_used: 0, })
}
///|
/// Returns every pending delivery in FIFO order and empties the outbox.
pub fn InMemoryOutbox::take_all(
self : InMemoryOutbox,
) -> Array[PendingDelivery] {
let result = self.entries.copy()
while !self.entries.is_empty() {
self.entries.pop() |> ignore
}
result
}
///|
pub fn InMemoryOutbox::length(self : InMemoryOutbox) -> Int {
self.entries.length()
}
///|
pub fn InMemoryOutbox::is_empty(self : InMemoryOutbox) -> Bool {
self.entries.is_empty()
}
///|
pub struct InMemoryDeadLetter {
entries : Array[DeadLetterEntry]
} derive(@debug.Debug)
///|
pub fn InMemoryDeadLetter::new() -> InMemoryDeadLetter {
{ entries: [], }
}
///|
pub fn InMemoryDeadLetter::push(
self : InMemoryDeadLetter,
entry : DeadLetterEntry,
) -> Unit {
self.entries.push(entry)
}
///|
pub fn InMemoryDeadLetter::list(
self : InMemoryDeadLetter,
) -> Array[DeadLetterEntry] {
self.entries.copy()
}
///|
pub fn InMemoryDeadLetter::length(self : InMemoryDeadLetter) -> Int {
self.entries.length()
}
///|
pub fn InMemoryDeadLetter::clear(self : InMemoryDeadLetter) -> Unit {
while !self.entries.is_empty() {
self.entries.pop() |> ignore
}
}