fix: attempt to only allow one deno process to update the node_modules folder at a time (#18058)

This is implemented in such a way that it should still allow processes
to go through when a file lock wasn't properly cleaned up and the OS
hasn't released it yet (but with a 200ms-ish delay).

Closes #18039
This commit is contained in:
David Sherret 2023-03-08 10:13:13 -05:00 committed by GitHub
parent 72fe9bb470
commit 88b5fd9088
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 301 additions and 7 deletions

View file

@ -23,6 +23,21 @@ mod renderer;
// Inspired by Indicatif, but this custom implementation allows
// for more control over what's going on under the hood.
#[derive(Debug, Clone, Copy)]
pub enum ProgressMessagePrompt {
Download,
Blocking,
}
impl ProgressMessagePrompt {
pub fn as_text(&self) -> String {
match self {
ProgressMessagePrompt::Download => colors::green("Download").to_string(),
ProgressMessagePrompt::Blocking => colors::cyan("Blocking").to_string(),
}
}
}
#[derive(Debug)]
pub struct UpdateGuard {
maybe_entry: Option<ProgressBarEntry>,
@ -59,6 +74,7 @@ pub enum ProgressBarStyle {
#[derive(Clone, Debug)]
struct ProgressBarEntry {
id: usize,
prompt: ProgressMessagePrompt,
pub message: String,
pos: Arc<AtomicU64>,
total_size: Arc<AtomicU64>,
@ -128,11 +144,16 @@ impl ProgressBarInner {
}
}
pub fn add_entry(&self, message: String) -> ProgressBarEntry {
pub fn add_entry(
&self,
kind: ProgressMessagePrompt,
message: String,
) -> ProgressBarEntry {
let mut internal_state = self.state.lock();
let id = internal_state.total_entries;
let entry = ProgressBarEntry {
id,
prompt: kind,
message,
pos: Default::default(),
total_size: Default::default(),
@ -208,6 +229,7 @@ impl DrawThreadRenderer for ProgressBarInner {
pending_entries: state.entries.len(),
total_entries: state.total_entries,
display_entry: ProgressDataDisplayEntry {
prompt: preferred_entry.prompt,
message: preferred_entry.message.clone(),
position: preferred_entry.position(),
total_size: preferred_entry.total_size(),
@ -255,9 +277,17 @@ impl ProgressBar {
}
pub fn update(&self, msg: &str) -> UpdateGuard {
self.update_with_prompt(ProgressMessagePrompt::Download, msg)
}
pub fn update_with_prompt(
&self,
kind: ProgressMessagePrompt,
msg: &str,
) -> UpdateGuard {
match &self.inner {
Some(inner) => {
let entry = inner.add_entry(msg.to_string());
let entry = inner.add_entry(kind, msg.to_string());
UpdateGuard {
maybe_entry: Some(entry),
}
@ -265,7 +295,7 @@ impl ProgressBar {
None => {
// if we're not running in TTY, fallback to using logger crate
if !msg.is_empty() {
log::log!(log::Level::Info, "{} {}", colors::green("Download"), msg);
log::log!(log::Level::Info, "{} {}", kind.as_text(), msg);
}
UpdateGuard { maybe_entry: None }
}

View file

@ -6,8 +6,11 @@ use deno_runtime::colors;
use crate::util::display::human_download_size;
use super::ProgressMessagePrompt;
#[derive(Clone)]
pub struct ProgressDataDisplayEntry {
pub prompt: ProgressMessagePrompt,
pub message: String,
pub position: u64,
pub total_size: u64,
@ -142,7 +145,7 @@ impl ProgressBarRenderer for TextOnlyProgressBarRenderer {
format!(
"{} {}{}{}",
colors::green("Download"),
data.display_entry.prompt.as_text(),
data.display_entry.message,
colors::gray(bytes_text),
colors::gray(total_text),
@ -195,6 +198,7 @@ mod test {
let renderer = BarProgressBarRenderer;
let mut data = ProgressData {
display_entry: ProgressDataDisplayEntry {
prompt: ProgressMessagePrompt::Download,
message: "data".to_string(),
position: 0,
total_size: 10 * BYTES_TO_KIB,
@ -251,6 +255,7 @@ mod test {
let renderer = TextOnlyProgressBarRenderer;
let mut data = ProgressData {
display_entry: ProgressDataDisplayEntry {
prompt: ProgressMessagePrompt::Blocking,
message: "data".to_string(),
position: 0,
total_size: 10 * BYTES_TO_KIB,
@ -263,7 +268,7 @@ mod test {
};
let text = renderer.render(data.clone());
let text = test_util::strip_ansi_codes(&text);
assert_eq!(text, "Download data 0.00KiB/10.00KiB (2/3)");
assert_eq!(text, "Blocking data 0.00KiB/10.00KiB (2/3)");
data.pending_entries = 0;
data.total_entries = 1;
@ -271,6 +276,6 @@ mod test {
data.display_entry.total_size = 0;
let text = renderer.render(data);
let text = test_util::strip_ansi_codes(&text);
assert_eq!(text, "Download data");
assert_eq!(text, "Blocking data");
}
}