Queued

Struct Queued 

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

An asynchronous, thread-pooled logger with guaranteed completion.

AsyncLogger acts as an orchestration layer that offloads logging side-effects to a background pool of workers. It is designed for high-throughput scenarios where log generation should not block the main application execution.

§Architecture: The “Traveling Sender” Pattern

This logger implements a resilient dispatch system using [crossbeam] channels. Each Message is wrapped in a PerishableMessage which carries its own [Sender] clone. This ensures that:

  1. Decoupled Retries: Workers can re-queue failed tasks without needing access to the parent logger’s state.
  2. Lifespan Tracking: Messages have a finite number of lives, preventing infinite loops in case of persistent service failure.

§Graceful Shutdown & Persistence

The AsyncLogger guarantees that no log is lost during program termination:

  • Drain Policy: On drop(), the primary sender is destroyed. Workers will continue processing until the internal buffer is empty and all re-queue attempts (lives) are exhausted.
  • Thread Synchronization: The logger waits (join) for all worker threads to finish their tasks before allowing the process to exit.

§Important Design Considerations

  • Ordering: Because this logger uses multiple concurrent workers (MPMC), strict chronological ordering is not guaranteed. While each Message retains its original timestamp, the order in which they reach the final destination may vary due to thread scheduling and retry logic.
  • Compatibility: This pattern is ideal for I/O-bound services like local files or standard streams. It is not recommended for services requiring strict sequential consistency (e.g., Loki or Aws).

§Example

let service = StandardCoutWrite::new();
let logger = QueuedLogger::new(service, 3, 4); // 3 retries, 4 worker threads
let logger = Logger::new(logger);
logger.log((LogLevel::Info,"System started"));

Implementations§

Source§

impl Queued

Source

pub fn new( service: Box<dyn Service + Send + Sync>, max_retries: usize, worker_count: usize, ) -> Box<Self>

Creates a new QueuedLogger and initializes the worker pool.

§Arguments
  • service - The logging service implementation.
  • max_retries - How many times a failed log should be re-queued.
  • worker_count - The number of background threads to spawn.
Source

pub fn get_service(&self) -> &dyn Service

Returns the base service

Source

pub fn take_service(self) -> Arc<dyn Service + Send + Sync>

Consumes the logger and returns the underlying service.

This method will block the current thread until all background workers have finished processing the current queue and all retries have been exhausted. This ensures that the returned service is in a clean, idle state.

Trait Implementations§

Source§

impl Drop for Queued

Source§

fn drop(&mut self)

Orchestrates a graceful shutdown of the logger.

  1. The primary [Sender] is dropped (set to None).
  2. This does not immediately close the channel if messages are in the queue, as those messages carry their own [Sender] clones.
  3. Once all messages are processed/exhausted, the last [Sender] dies.
  4. worker_receiver.recv() returns Err, and threads exit.
  5. join() ensures all threads have finished before the program proceeds.
Source§

impl LoggerImpl for Queued

Source§

fn status(&self) -> LoggerStatus

Checks the health status of the underlying service.

Source§

fn log(&self, message: Message)

Dispatches a message to the background worker pool.

Each message is bundled with a clone of the sender to enable self-contained retry logic within the worker threads.

Source§

fn as_any(&self) -> &dyn Any

Downcasts the logger to Any for reflection-like capabilities.

Auto Trait Implementations§

§

impl Freeze for Queued

§

impl !RefUnwindSafe for Queued

§

impl Send for Queued

§

impl Sync for Queued

§

impl Unpin for Queued

§

impl !UnwindSafe for Queued

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.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more