Skip to main content

ProgressReporter

Struct ProgressReporter 

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

Progress reporter for multi-step operations

Tracks progress through multiple steps of a long-running operation, providing clear feedback with step numbers, descriptions, and timing.

§Examples

use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output, 2);

progress.start_step("Step 1")?;
progress.complete_step(Some("Step 1 done"))?;

progress.start_step("Step 2")?;
progress.complete_step(None)?;

progress.complete("All done!")?;

Implementations§

Source§

impl ProgressReporter

Source

pub fn new( output: Arc<ReentrantMutex<RefCell<UserOutput>>>, total_steps: usize, ) -> Self

Create a new progress reporter

§Arguments
  • output - Shared user output handler for displaying messages
  • total_steps - Total number of steps in the operation
§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let progress = ProgressReporter::new(output, 5);
Source

pub fn start_step( &mut self, description: &str, ) -> Result<(), ProgressReporterError>

Start a new step with a description

Increments the current step counter and displays a progress message in the format [current/total] description....

§Arguments
  • description - Human-readable description of what this step does
§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output, 3);

progress.start_step("Loading configuration")?;
// Output: ⏳ [1/3] Loading configuration...
Source

pub fn complete_step( &mut self, result: Option<&str>, ) -> Result<(), ProgressReporterError>

Complete the current step with optional result message

Displays a completion message with timing information. The message shows either the provided result or a generic “Done” message.

§Arguments
  • result - Optional description of what was accomplished
§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output, 2);

progress.start_step("Loading data")?;
progress.complete_step(Some("Data loaded successfully"))?;
// Output: ✓ Data loaded successfully (took 150ms)

progress.start_step("Processing")?;
progress.complete_step(None)?;
// Output: ✓ Done (took 2.3s)
Source

pub fn sub_step( &mut self, description: &str, ) -> Result<(), ProgressReporterError>

Report a sub-step within the current step

Displays an indented message indicating progress within the current step. Useful for showing detailed progress without starting a new numbered step.

§Arguments
  • description - What is currently happening within this step
§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output.clone(), 1);

progress.start_step("Provisioning infrastructure")?;
progress.sub_step("Creating virtual machine")?;
progress.sub_step("Configuring network")?;
progress.sub_step("Setting up storage")?;
progress.complete_step(Some("Infrastructure ready"))?;
Source

pub fn complete(&mut self, summary: &str) -> Result<(), ProgressReporterError>

Complete all steps and show summary

Displays a final success message indicating the entire operation completed. This should be called after all steps are done.

§Arguments
  • summary - Final success message describing what was accomplished
§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output.clone(), 1);

progress.start_step("Creating environment")?;
progress.complete_step(None)?;
progress.complete("Environment 'test-env' created successfully")?;
// Output: ✅ Environment 'test-env' created successfully
Source

pub fn output(&self) -> &Arc<ReentrantMutex<RefCell<UserOutput>>>

Get a reference to the shared UserOutput

This allows using other output methods (like error, warn) while progress is being tracked.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output.clone(), 1);

progress.start_step("Checking conditions");
progress.output().lock().borrow_mut().warn("Some non-critical warning");
progress.complete_step(None);
Source

pub fn blank_line(&self) -> Result<(), ProgressReporterError>

Add a blank line to the output

This is a wrapper around UserOutput::blank_line() that handles mutex acquisition with timeout protection.

§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned. Returns ProgressReporterError::UserOutputMutexTimeout if the mutex cannot be acquired within the timeout.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output, 3);

progress.blank_line()?;
Source

pub fn steps( &self, title: &str, steps: &[&str], ) -> Result<(), ProgressReporterError>

Display a list of steps with a title

This is a wrapper around UserOutput::steps() that handles mutex acquisition with timeout protection.

§Arguments
  • title - The title for the steps list
  • steps - Array of step descriptions
§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned. Returns ProgressReporterError::UserOutputMutexTimeout if the mutex cannot be acquired within the timeout.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let mut progress = ProgressReporter::new(output, 3);

progress.steps("Next steps:", &[
    "Edit the configuration file",
    "Review the settings",
    "Run the deploy command"
])?;
Source

pub fn result(&self, message: &str) -> Result<(), ProgressReporterError>

Output result data to stdout

Wraps UserOutput::result() to write result data to stdout. Result data goes to stdout (not stderr) so it can be piped or redirected.

§Arguments ///
  • message - The result data to output
§Errors

Returns error if the user output mutex is poisoned

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let progress = ProgressReporter::new(output, 1);

progress.result(r#"{"schema": "..."}"#)?;
Source

pub fn warn(&self, message: &str) -> Result<(), ProgressReporterError>

Display a warning message to stderr

Wraps UserOutput::warn() for use during progress-tracked workflows. Warnings are non-blocking — they do not stop the current operation.

§Arguments
  • message - Warning text (may contain newlines for multi-line warnings)
§Errors

Returns ProgressReporterError::UserOutputMutexPoisoned if the mutex is poisoned.

§Examples
use std::sync::Arc;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
use torrust_tracker_deployer_lib::presentation::cli::views::progress::ProgressReporter;
use torrust_tracker_deployer_lib::presentation::cli::views::{UserOutput, VerbosityLevel};

let output = Arc::new(ReentrantMutex::new(RefCell::new(UserOutput::new(VerbosityLevel::Normal))));
let progress = ProgressReporter::new(output, 1);

progress.warn("SSH key appears to be passphrase-protected")?;

Auto Trait Implementations§

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> Instrument for T

Source§

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

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

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

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> IntoResult<T> for T

Source§

type Err = !

Source§

fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>

Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

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

Initializes a with the given initializer. Read more
Source§

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

Dereferences the given pointer. Read more
Source§

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

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

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

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

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + 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
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + 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 = !

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

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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