Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spinner not spinning #588

Closed
rawhuul opened this issue Sep 17, 2023 · 6 comments
Closed

Spinner not spinning #588

rawhuul opened this issue Sep 17, 2023 · 6 comments

Comments

@rawhuul
Copy link

rawhuul commented Sep 17, 2023

Hey there, this is my code:

impl SyncAll for Buckets {
    type Error = ScoopieError;
    fn sync() -> Result<Vec<SyncStatus>, Self::Error> {
        let buckets = Config::read()?.known_buckets();
        let num_buckets = buckets.len();

        let st = ProgressStyle::with_template("{spinner:.bold} ({pos}/{len}) {msg}").unwrap();

        let pb = ProgressBar::new(num_buckets as u64);
        pb.set_style(st);
        pb.set_message(
            style("Syncing buckets from the remote...")
                .bold()
                .to_string(),
        );

        buckets
            .par_iter()
            .map(|v| Bucket::sync(&pb, v.0, v.1))
            .collect()
    }
}

trait Sync: ReadFromRepo {
    type Error;
    fn sync(pb: &ProgressBar, name: &str, url: &str) -> Result<SyncStatus, <Self as Sync>::Error>;
}

impl Sync for Bucket {
    type Error = ScoopieError;

    fn sync(pb: &ProgressBar, name: &str, url: &str) -> Result<SyncStatus, <Self as Sync>::Error> {
        let temp_dir_builder = TempDir::build()?;
        let temp_dir = temp_dir_builder.path();

        let repo = RepoBuilder::new()
            .clone(url, &temp_dir)
            .map_err(|_| ScoopieError::SyncUnableToFetchRepo)?;

        let head = repo.head().map_err(|_| ScoopieError::SyncUnableToGetHead)?;

        let commit_id = head
            .peel_to_commit()
            .map_err(|_| ScoopieError::SyncUnableToGetCommit)?
            .id()
            .to_string();

        let bucket_dir = Config::buckets_dir()?;
        let bucket_path = bucket_dir.join(name);

        let mut metadata = MetaData::read()?;

        let st = match (
            bucket_path.exists(),
            metadata.get(name).commit_id == commit_id,
        ) {
            (true, true) => SyncStatus::UpToDate(name.into()),
            (true, false) => {
                Self::read(&temp_dir)?.write_to(&bucket_path);
                metadata.write(name, url, &commit_id)?;
                SyncStatus::Synced(name.into())
            }

            (false, _) => {
                Self::read(&temp_dir)?.write_to(&bucket_path);
                metadata.write(name, url, &commit_id)?;
                SyncStatus::Created(name.into())
            }
        };

        pb.inc(1);

        Ok(st)
    }
}

Everything work as expected but the spinner is not spinning as expected it is intended to be spin indefinitely without stopping until all function returns.

not_spinning.mp4

My Cargo.toml looks like:

...
indicatif = { version = "0.17.6", features = ["rayon"] }

# To show colors in terminal
console = "0.15.7"
@djc
Copy link
Member

djc commented Sep 18, 2023

Can you turn this into a minimal reproduction that doesn't have any dependencies other than indicatif?

@rawhuul
Copy link
Author

rawhuul commented Sep 18, 2023

Yeah sure.

Here is the code,

use indicatif::{ProgressBar, ProgressStyle};
use rayon::prelude::*;

fn waiting(pb: &ProgressBar, n: i32) -> i32 {
    std::thread::sleep(std::time::Duration::from_secs(10));
    pb.inc(1);

    n * n
}

fn main() {
    let st = ProgressStyle::with_template("{spinner:.bold} ({pos}/{len}) {msg}").unwrap();

    let pb = ProgressBar::new(4 as u64);
    pb.set_style(st);
    pb.set_message("Syncing buckets from the remote...");

    let v = (1..4)
        .into_par_iter()
        .map(|n| waiting(&pb, n))
        .collect::<Vec<_>>();

    println!("{v:#?}");
}

Cargo.toml:

[package]
name = "indi"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
indicatif = { version = "0.17.6", features = ["rayon"] }
rayon = "1.7.0"

Results:

indi.mp4

As you can see spinner is stuck and only spins after function returns, whereas it must be spinning all the time unless the spinner finishes (I guess it should be intended).

@djc
Copy link
Member

djc commented Sep 22, 2023

I think this behavior is expected? indicatif doesn't spawn a separate thread unless you explicitly enable that (using enable_steady_tick()), so unless you do that the spinner will only update whenever you call pb.inc().

@chris-laplante
Copy link
Collaborator

Yes, this is expected behavior. Perhaps we need a documentation change to make it clear that a '{spinner}' doesn't automatically update unless something is driving it. I'd be happy to submit a PR for that.

@djc
Copy link
Member

djc commented Sep 22, 2023

@chris-laplante please do!

@chris-laplante
Copy link
Collaborator

I documented this in #593 and then forgot to close this issue. Closing now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants