diff --git a/linera-chain/src/outbox.rs b/linera-chain/src/outbox.rs index 9043796301d..711bd970d87 100644 --- a/linera-chain/src/outbox.rs +++ b/linera-chain/src/outbox.rs @@ -10,18 +10,19 @@ use linera_views::{ register_view::RegisterView, views::{ClonableView, View, ViewError}, }; +use log::info; // Import logging for debugging #[cfg(test)] #[path = "unit_tests/outbox_tests.rs"] mod outbox_tests; -/// The state of an outbox +/// The state of an outbox. +/// /// * An outbox is used to send messages to another chain. /// * Internally, this is implemented as a FIFO queue of (increasing) block heights. -/// Messages are contained in blocks, together with destination information, so currently -/// we just send the certified blocks over and let the receivers figure out what were the -/// messages for them. -/// * When marking block heights as received, messages at lower heights are also marked (ie. dequeued). +/// Messages are contained in blocks, together with destination information, so currently, +/// we just send the certified blocks over and let the receivers figure out what the messages are for them. +/// * When marking block heights as received, messages at lower heights are also marked (i.e., dequeued). #[derive(Debug, ClonableView, View, async_graphql::SimpleObject)] pub struct OutboxStateView where @@ -29,8 +30,8 @@ where { /// The minimum block height accepted in the future. pub next_height_to_schedule: RegisterView, - /// Keep sending these certified blocks of ours until they are acknowledged by - /// receivers. + + /// The queue of certified blocks that need to be sent until they are acknowledged by receivers. pub queue: QueueView, } @@ -38,22 +39,37 @@ impl OutboxStateView where C: Context + Clone + Send + Sync + 'static, { - /// Schedules a message at the given height if we haven't already. - /// Returns true if a change was made. + /// Schedules a message at the given block height if it hasn't already been scheduled. + /// Returns `true` if a change was made. + /// + /// # Errors + /// Returns `ArithmeticError` if there is an overflow when incrementing the block height. pub(crate) fn schedule_message( &mut self, height: BlockHeight, ) -> Result { if height < *self.next_height_to_schedule.get() { + info!("Skipping scheduling for block height {}: already past", height); return Ok(false); } + + // Increment the height and schedule the message self.next_height_to_schedule.set(height.try_add_one()?); self.queue.push_back(height); + + info!("Scheduled block height {} successfully", height); Ok(true) } - /// Marks all messages as received up to the given height. - /// Returns true if a change was made. + /// Marks all messages as received up to the given block height. + /// + /// This method processes all messages in the queue that have a height less than or equal to the provided `height`, + /// removing them from the queue and returning a list of processed heights. + /// This ensures that messages are acknowledged in a FIFO manner. + /// + /// # Returns + /// - `Ok(Vec)` – a list of heights that were successfully marked as received. + /// - `Err(ViewError)` – if an error occurs while processing the queue. pub(crate) async fn mark_messages_as_received( &mut self, height: BlockHeight, @@ -66,6 +82,8 @@ where self.queue.delete_front(); updates.push(h); } + + info!("Marked {} messages as received", updates.len()); Ok(updates) } } @@ -75,10 +93,20 @@ impl OutboxStateView> where MemoryContext<()>: Context + Clone + Send + Sync + 'static, { + /// Creates a new OutboxStateView with an in-memory test context. + /// + /// This is used for testing purposes to simulate the behavior of the outbox. pub async fn new() -> Self { let context = create_test_memory_context(); Self::load(context) .await .expect("Loading from memory should work") } + + /// Clears the state of the outbox, including the queue and the next height to schedule. + pub async fn clear(&mut self) { + self.queue.clear().await; + self.next_height_to_schedule.set(BlockHeight::default()); + info!("Outbox state cleared."); + } }