Skip to content

Commit

Permalink
refactor: add WatcherCommunicator helper struct (denoland#20927)
Browse files Browse the repository at this point in the history
This commit introduces "WatcherCommunicator" struct that
is used facilitate bi-directional communication between CLI
file watcher and the watched function.

Prerequisite for denoland#20876
  • Loading branch information
bartlomieju committed Oct 19, 2023
1 parent 5095af7 commit 8d9fef3
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 90 deletions.
39 changes: 22 additions & 17 deletions cli/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use crate::resolver::CliGraphResolver;
use crate::resolver::CliGraphResolverOptions;
use crate::standalone::DenoCompileBinaryWriter;
use crate::tools::check::TypeChecker;
use crate::util::file_watcher::WatcherCommunicator;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::worker::CliMainWorkerFactory;
Expand All @@ -59,26 +60,18 @@ use deno_runtime::inspector_server::InspectorServer;
use deno_semver::npm::NpmPackageReqReference;
use import_map::ImportMap;
use log::warn;
use std::cell::RefCell;
use std::future::Future;
use std::path::PathBuf;
use std::sync::Arc;

pub struct CliFactoryBuilder {
maybe_sender: Option<tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>>,
watcher_communicator: Option<WatcherCommunicator>,
}

impl CliFactoryBuilder {
pub fn new() -> Self {
Self { maybe_sender: None }
}

pub fn with_watcher(
mut self,
sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
) -> Self {
self.maybe_sender = Some(sender);
self
Self {
watcher_communicator: None,
}
}

pub async fn build_from_flags(
Expand All @@ -88,9 +81,18 @@ impl CliFactoryBuilder {
Ok(self.build_from_cli_options(Arc::new(CliOptions::from_flags(flags)?)))
}

pub async fn build_from_flags_for_watcher(
mut self,
flags: Flags,
watcher_communicator: WatcherCommunicator,
) -> Result<CliFactory, AnyError> {
self.watcher_communicator = Some(watcher_communicator);
self.build_from_flags(flags).await
}

pub fn build_from_cli_options(self, options: Arc<CliOptions>) -> CliFactory {
CliFactory {
maybe_sender: RefCell::new(self.maybe_sender),
watcher_communicator: self.watcher_communicator,
options,
services: Default::default(),
}
Expand Down Expand Up @@ -166,8 +168,7 @@ struct CliFactoryServices {
}

pub struct CliFactory {
maybe_sender:
RefCell<Option<tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>>>,
watcher_communicator: Option<WatcherCommunicator>,
options: Arc<CliOptions>,
services: CliFactoryServices,
}
Expand Down Expand Up @@ -384,11 +385,14 @@ impl CliFactory {
}

pub fn maybe_file_watcher_reporter(&self) -> &Option<FileWatcherReporter> {
let maybe_sender = self.maybe_sender.borrow_mut().take();
let maybe_file_watcher_reporter = self
.watcher_communicator
.as_ref()
.map(|i| FileWatcherReporter::new(i.clone()));
self
.services
.maybe_file_watcher_reporter
.get_or_init(|| maybe_sender.map(FileWatcherReporter::new))
.get_or_init(|| maybe_file_watcher_reporter)
}

pub fn emit_cache(&self) -> Result<&EmitCache, AnyError> {
Expand Down Expand Up @@ -595,6 +599,7 @@ impl CliFactory {
let npm_resolver = self.npm_resolver().await?;
let fs = self.fs();
let cli_node_resolver = self.cli_node_resolver().await?;

Ok(CliMainWorkerFactory::new(
StorageKeyResolver::from_options(&self.options),
npm_resolver.clone(),
Expand Down
12 changes: 8 additions & 4 deletions cli/graph_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver;
use crate::tools::check;
use crate::tools::check::TypeChecker;
use crate::util::file_watcher::WatcherCommunicator;
use crate::util::sync::TaskQueue;
use crate::util::sync::TaskQueuePermit;

Expand Down Expand Up @@ -635,14 +636,14 @@ impl<'a> ModuleGraphUpdatePermit<'a> {

#[derive(Clone, Debug)]
pub struct FileWatcherReporter {
sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
watcher_communicator: WatcherCommunicator,
file_paths: Arc<Mutex<Vec<PathBuf>>>,
}

impl FileWatcherReporter {
pub fn new(sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>) -> Self {
pub fn new(watcher_communicator: WatcherCommunicator) -> Self {
Self {
sender,
watcher_communicator,
file_paths: Default::default(),
}
}
Expand All @@ -665,7 +666,10 @@ impl deno_graph::source::Reporter for FileWatcherReporter {
}

if modules_done == modules_total {
self.sender.send(file_paths.drain(..).collect()).unwrap();
self
.watcher_communicator
.watch_paths(file_paths.drain(..).collect())
.unwrap();
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions cli/tools/bench/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,19 +417,18 @@ pub async fn run_benchmarks_with_watch(
.map(|w| !w.no_clear_screen)
.unwrap_or(true),
},
move |flags, sender, changed_paths| {
move |flags, watcher_communicator, changed_paths| {
let bench_flags = bench_flags.clone();
Ok(async move {
let factory = CliFactoryBuilder::new()
.with_watcher(sender.clone())
.build_from_flags(flags)
.build_from_flags_for_watcher(flags, watcher_communicator.clone())
.await?;
let cli_options = factory.cli_options();
let bench_options = cli_options.resolve_bench_options(bench_flags)?;

let _ = sender.send(cli_options.watch_paths());
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
if let Some(include) = &bench_options.files.include {
let _ = sender.send(include.clone());
let _ = watcher_communicator.watch_paths(include.clone());
}

let graph_kind = cli_options.type_check_mode().as_graph_kind();
Expand Down
7 changes: 3 additions & 4 deletions cli/tools/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ pub async fn bundle(
job_name: "Bundle".to_string(),
clear_screen: !watch_flags.no_clear_screen,
},
move |flags, sender, _changed_paths| {
move |flags, watcher_communicator, _changed_paths| {
let bundle_flags = bundle_flags.clone();
Ok(async move {
let factory = CliFactoryBuilder::new()
.with_watcher(sender.clone())
.build_from_flags(flags)
.build_from_flags_for_watcher(flags, watcher_communicator.clone())
.await?;
let cli_options = factory.cli_options();
let _ = sender.send(cli_options.watch_paths());
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
bundle_action(factory, &bundle_flags).await?;

Ok(())
Expand Down
4 changes: 2 additions & 2 deletions cli/tools/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub async fn format(flags: Flags, fmt_flags: FmtFlags) -> Result<(), AnyError> {
job_name: "Fmt".to_string(),
clear_screen: !watch_flags.no_clear_screen,
},
move |flags, sender, changed_paths| {
move |flags, watcher_communicator, changed_paths| {
let fmt_flags = fmt_flags.clone();
Ok(async move {
let factory = CliFactory::from_flags(flags).await?;
Expand All @@ -82,7 +82,7 @@ pub async fn format(flags: Flags, fmt_flags: FmtFlags) -> Result<(), AnyError> {
Ok(files)
}
})?;
_ = sender.send(files.clone());
_ = watcher_communicator.watch_paths(files.clone());
let refmt_files = if let Some(paths) = changed_paths {
if fmt_options.check {
// check all files on any changed (https://github.com/denoland/deno/issues/12446)
Expand Down
4 changes: 2 additions & 2 deletions cli/tools/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
job_name: "Lint".to_string(),
clear_screen: !watch_flags.no_clear_screen,
},
move |flags, sender, changed_paths| {
move |flags, watcher_communicator, changed_paths| {
let lint_flags = lint_flags.clone();
Ok(async move {
let factory = CliFactory::from_flags(flags).await?;
Expand All @@ -77,7 +77,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
Ok(files)
}
})?;
_ = sender.send(files.clone());
_ = watcher_communicator.watch_paths(files.clone());

let lint_paths = if let Some(paths) = changed_paths {
// lint all files on any changed (https://github.com/denoland/deno/issues/12446)
Expand Down
7 changes: 3 additions & 4 deletions cli/tools/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,17 @@ async fn run_with_watch(
job_name: "Process".to_string(),
clear_screen: !watch_flags.no_clear_screen,
},
move |flags, sender, _changed_paths| {
move |flags, watcher_communicator, _changed_paths| {
Ok(async move {
let factory = CliFactoryBuilder::new()
.with_watcher(sender.clone())
.build_from_flags(flags)
.build_from_flags_for_watcher(flags, watcher_communicator.clone())
.await?;
let cli_options = factory.cli_options();
let main_module = cli_options.resolve_main_module()?;

maybe_npm_install(&factory).await?;

let _ = sender.send(cli_options.watch_paths());
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());

let permissions = PermissionsContainer::new(Permissions::from_options(
&cli_options.permissions_options(),
Expand Down
9 changes: 4 additions & 5 deletions cli/tools/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,19 +1213,18 @@ pub async fn run_tests_with_watch(
.map(|w| !w.no_clear_screen)
.unwrap_or(true),
},
move |flags, sender, changed_paths| {
move |flags, watcher_communicator, changed_paths| {
let test_flags = test_flags.clone();
Ok(async move {
let factory = CliFactoryBuilder::new()
.with_watcher(sender.clone())
.build_from_flags(flags)
.build_from_flags_for_watcher(flags, watcher_communicator.clone())
.await?;
let cli_options = factory.cli_options();
let test_options = cli_options.resolve_test_options(test_flags)?;

let _ = sender.send(cli_options.watch_paths());
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
if let Some(include) = &test_options.files.include {
let _ = sender.send(include.clone());
let _ = watcher_communicator.watch_paths(include.clone());
}

let graph_kind = cli_options.type_check_mode().as_graph_kind();
Expand Down
Loading

0 comments on commit 8d9fef3

Please sign in to comment.