Skip to content

Commit 0e749f0

Browse files
authored
feat: persistent cache expose error to compilation.diagnostic (#8765)
1 parent 8aeb507 commit 0e749f0

File tree

12 files changed

+167
-132
lines changed

12 files changed

+167
-132
lines changed

crates/rspack_core/src/cache/disable.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use rspack_error::Result;
2+
13
use super::Cache;
24
use crate::make::MakeArtifact;
35

@@ -9,7 +11,8 @@ pub struct DisableCache;
911

1012
#[async_trait::async_trait]
1113
impl Cache for DisableCache {
12-
async fn before_make(&self, make_artifact: &mut MakeArtifact) {
14+
async fn before_make(&self, make_artifact: &mut MakeArtifact) -> Result<()> {
1315
*make_artifact = Default::default();
16+
Ok(())
1417
}
1518
}

crates/rspack_core/src/cache/mod.rs

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod persistent;
44

55
use std::{fmt::Debug, sync::Arc};
66

7+
use rspack_error::Result;
78
use rspack_fs::{FileSystem, IntermediateFileSystem};
89

910
pub use self::{disable::DisableCache, memory::MemoryCache, persistent::PersistentCache};
@@ -23,11 +24,19 @@ use crate::{make::MakeArtifact, Compilation, CompilerOptions, ExperimentCacheOpt
2324
/// We can consider change to Hook when we need to open the API to js side.
2425
#[async_trait::async_trait]
2526
pub trait Cache: Debug + Send + Sync {
26-
async fn before_compile(&self, _compilation: &mut Compilation) {}
27-
fn after_compile(&self, _compilation: &Compilation) {}
27+
async fn before_compile(&self, _compilation: &mut Compilation) -> Result<()> {
28+
Ok(())
29+
}
30+
async fn after_compile(&self, _compilation: &Compilation) -> Result<()> {
31+
Ok(())
32+
}
2833

29-
async fn before_make(&self, _make_artifact: &mut MakeArtifact) {}
30-
fn after_make(&self, _make_artifact: &MakeArtifact) {}
34+
async fn before_make(&self, _make_artifact: &mut MakeArtifact) -> Result<()> {
35+
Ok(())
36+
}
37+
async fn after_make(&self, _make_artifact: &MakeArtifact) -> Result<()> {
38+
Ok(())
39+
}
3140
}
3241

3342
pub fn new_cache(
@@ -39,20 +48,12 @@ pub fn new_cache(
3948
match &compiler_option.experiments.cache {
4049
ExperimentCacheOptions::Disabled => Arc::new(DisableCache),
4150
ExperimentCacheOptions::Memory => Arc::new(MemoryCache),
42-
ExperimentCacheOptions::Persistent(option) => {
43-
match PersistentCache::new(
44-
compiler_path,
45-
option,
46-
compiler_option.clone(),
47-
input_filesystem,
48-
intermediate_filesystem,
49-
) {
50-
Ok(cache) => Arc::new(cache),
51-
Err(e) => {
52-
tracing::warn!("create persistent cache failed {e:?}");
53-
Arc::new(MemoryCache)
54-
}
55-
}
56-
}
51+
ExperimentCacheOptions::Persistent(option) => Arc::new(PersistentCache::new(
52+
compiler_path,
53+
option,
54+
compiler_option.clone(),
55+
input_filesystem,
56+
intermediate_filesystem,
57+
)),
5758
}
5859
}

crates/rspack_core/src/cache/persistent/mod.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use std::{path::PathBuf, sync::Arc};
77

88
pub use cacheable_context::{CacheableContext, FromContext};
99
use occasion::MakeOccasion;
10-
use rspack_fs::{FileSystem, IntermediateFileSystem, Result};
10+
use rspack_error::Result;
11+
use rspack_fs::{FileSystem, IntermediateFileSystem};
1112
use rspack_macros::rspack_version;
1213
use rspack_paths::ArcPath;
1314
use rustc_hash::FxHashSet as HashSet;
@@ -42,39 +43,40 @@ impl PersistentCache {
4243
compiler_options: Arc<CompilerOptions>,
4344
input_filesystem: Arc<dyn FileSystem>,
4445
intermediate_filesystem: Arc<dyn IntermediateFileSystem>,
45-
) -> Result<Self> {
46+
) -> Self {
4647
let version = version::get_version(
4748
input_filesystem.clone(),
4849
&option.build_dependencies,
4950
vec![compiler_path, &option.version, rspack_version!()],
50-
)?;
51+
);
5152
let storage = create_storage(option.storage.clone(), version, intermediate_filesystem);
5253
let context = Arc::new(CacheableContext {
5354
options: compiler_options,
5455
input_filesystem: input_filesystem.clone(),
5556
});
5657
let make_occasion = MakeOccasion::new(storage.clone(), context);
57-
Ok(Self {
58+
Self {
5859
snapshot: Snapshot::new(option.snapshot.clone(), input_filesystem, storage.clone()),
5960
storage,
6061
make_occasion,
61-
})
62+
}
6263
}
6364
}
6465

6566
#[async_trait::async_trait]
6667
impl Cache for PersistentCache {
67-
async fn before_compile(&self, compilation: &mut Compilation) {
68+
async fn before_compile(&self, compilation: &mut Compilation) -> Result<()> {
6869
if compilation.modified_files.is_empty() && compilation.removed_files.is_empty() {
6970
// inject modified_files and removed_files
70-
let (modified_paths, removed_paths) = self.snapshot.calc_modified_paths().await;
71+
let (modified_paths, removed_paths) = self.snapshot.calc_modified_paths().await?;
7172
tracing::info!("cache::snapshot recovery {modified_paths:?} {removed_paths:?}",);
7273
compilation.modified_files = modified_paths;
7374
compilation.removed_files = removed_paths;
7475
}
76+
Ok(())
7577
}
7678

77-
fn after_compile(&self, compilation: &Compilation) {
79+
async fn after_compile(&self, compilation: &Compilation) -> Result<()> {
7880
// TODO add a all_dependencies to collect dependencies
7981
let (_, file_added, file_removed) = compilation.file_dependencies();
8082
let (_, context_added, context_removed) = compilation.context_dependencies();
@@ -103,24 +105,24 @@ impl Cache for PersistentCache {
103105
.remove(removed_paths.iter().map(|item| item.as_ref()));
104106
self
105107
.snapshot
106-
.add(modified_paths.iter().map(|item| item.as_ref()));
108+
.add(modified_paths.iter().map(|item| item.as_ref()))
109+
.await;
107110

108111
// TODO listen for storage finish in build mode
109112
let _ = self.storage.trigger_save();
113+
114+
Ok(())
110115
}
111116

112-
async fn before_make(&self, make_artifact: &mut MakeArtifact) {
117+
async fn before_make(&self, make_artifact: &mut MakeArtifact) -> Result<()> {
113118
if !make_artifact.initialized {
114-
match self.make_occasion.recovery().await {
115-
Ok(artifact) => *make_artifact = artifact,
116-
Err(err) => {
117-
tracing::warn!("recovery error with {err:?}")
118-
}
119-
}
119+
*make_artifact = self.make_occasion.recovery().await?;
120120
}
121+
Ok(())
121122
}
122123

123-
fn after_make(&self, make_artifact: &MakeArtifact) {
124+
async fn after_make(&self, make_artifact: &MakeArtifact) -> Result<()> {
124125
self.make_occasion.save(make_artifact);
126+
Ok(())
125127
}
126128
}

crates/rspack_core/src/cache/persistent/occasion/make/dependencies.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::sync::{Arc, Mutex};
22

33
use rayon::prelude::*;
4-
use rspack_cacheable::{
5-
cacheable, from_bytes, to_bytes, with::Inline, DeserializeError, SerializeError,
6-
};
4+
use rspack_cacheable::{cacheable, from_bytes, to_bytes, with::Inline};
5+
use rspack_error::Result;
76
use rspack_paths::ArcPath;
87
use rustc_hash::FxHashMap as HashMap;
98

@@ -45,7 +44,7 @@ pub fn save_dependencies_info(
4544
missing_dependencies: &FileCounter,
4645
build_dependencies: &FileCounter,
4746
storage: &Arc<dyn Storage>,
48-
) -> Result<(), SerializeError> {
47+
) {
4948
let f = file_dependencies
5049
.updated_files_count_info()
5150
.map(|(path, count)| {
@@ -98,37 +97,35 @@ pub fn save_dependencies_info(
9897
.chain(m)
9998
.chain(b)
10099
.par_bridge()
101-
.try_for_each(|(dep_ref, count)| {
102-
let dep_ref = to_bytes(&dep_ref, &())?;
100+
.for_each(|(dep_ref, count)| {
101+
let dep_ref = to_bytes(&dep_ref, &()).expect("should to bytes success");
103102
if count == 0 {
104103
storage.remove(SCOPE, &dep_ref);
105104
} else {
106105
storage.set(SCOPE, dep_ref, count.to_ne_bytes().to_vec());
107106
}
108-
Ok(())
109-
})
107+
});
110108
}
111109

112110
pub async fn recovery_dependencies_info(
113111
storage: &Arc<dyn Storage>,
114-
) -> Result<(FileCounter, FileCounter, FileCounter, FileCounter), DeserializeError> {
112+
) -> Result<(FileCounter, FileCounter, FileCounter, FileCounter)> {
115113
let file_dep = Mutex::new(HashMap::default());
116114
let context_dep = Mutex::new(HashMap::default());
117115
let missing_dep = Mutex::new(HashMap::default());
118116
let build_dep = Mutex::new(HashMap::default());
119117
storage
120118
.load(SCOPE)
121-
.await
122-
.unwrap_or_default()
119+
.await?
123120
.into_par_iter()
124-
.try_for_each(|(k, v)| {
121+
.for_each(|(k, v)| {
125122
let count = usize::from_ne_bytes(
126123
v.as_ref()
127124
.clone()
128125
.try_into()
129-
.map_err(|_| DeserializeError::MessageError("deserialize count failed"))?,
126+
.expect("should parse count success"),
130127
);
131-
let Dependency { r#type, path } = from_bytes(&k, &())?;
128+
let Dependency { r#type, path } = from_bytes(&k, &()).expect("should from bytes success");
132129
match r#type {
133130
DepType::File => file_dep
134131
.lock()
@@ -147,8 +144,7 @@ pub async fn recovery_dependencies_info(
147144
.expect("should get build dep")
148145
.insert(path, count),
149146
};
150-
Ok(())
151-
})?;
147+
});
152148

153149
Ok((
154150
FileCounter::new(file_dep.into_inner().expect("into_inner should be success")),

crates/rspack_core/src/cache/persistent/occasion/make/meta.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::sync::{atomic::Ordering::Relaxed, Arc};
22

3-
use rspack_cacheable::{
4-
cacheable, from_bytes, to_bytes, with::Inline, DeserializeError, SerializeError,
5-
};
3+
use rspack_cacheable::{cacheable, from_bytes, to_bytes, with::Inline};
64
use rspack_collections::IdentifierSet;
5+
use rspack_error::Result;
76
use rustc_hash::FxHashSet as HashSet;
87

98
use super::Storage;
@@ -34,23 +33,26 @@ pub fn save_meta(
3433
make_failed_dependencies: &HashSet<BuildDependency>,
3534
make_failed_module: &IdentifierSet,
3635
storage: &Arc<dyn Storage>,
37-
) -> Result<(), SerializeError> {
36+
) {
3837
let meta = MetaRef {
3938
make_failed_dependencies,
4039
make_failed_module,
4140
next_dependencies_id: DEPENDENCY_ID.load(Relaxed),
4241
};
43-
storage.set(SCOPE, "default".as_bytes().to_vec(), to_bytes(&meta, &())?);
44-
Ok(())
42+
storage.set(
43+
SCOPE,
44+
"default".as_bytes().to_vec(),
45+
to_bytes(&meta, &()).expect("should to bytes success"),
46+
);
4547
}
4648

4749
pub async fn recovery_meta(
4850
storage: &Arc<dyn Storage>,
49-
) -> Result<(HashSet<BuildDependency>, IdentifierSet), DeserializeError> {
50-
let Some((_, value)) = storage.load(SCOPE).await.unwrap_or_default().pop() else {
51-
return Err(DeserializeError::MessageError("can not get meta data"));
51+
) -> Result<(HashSet<BuildDependency>, IdentifierSet)> {
52+
let Some((_, value)) = storage.load(SCOPE).await?.pop() else {
53+
return Ok(Default::default());
5254
};
53-
let meta: Meta = from_bytes(&value, &())?;
55+
let meta: Meta = from_bytes(&value, &()).expect("should from bytes success");
5456
// TODO make dependency id to string like module id
5557
if DEPENDENCY_ID.load(Relaxed) < meta.next_dependencies_id {
5658
DEPENDENCY_ID.store(meta.next_dependencies_id, Relaxed);

crates/rspack_core/src/cache/persistent/occasion/make/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod module_graph;
44

55
use std::sync::Arc;
66

7-
use rspack_cacheable::DeserializeError;
7+
use rspack_error::Result;
88

99
use super::super::{cacheable_context::CacheableContext, Storage};
1010
use crate::make::MakeArtifact;
@@ -48,8 +48,7 @@ impl MakeOccasion {
4848
missing_dependencies,
4949
build_dependencies,
5050
&self.storage,
51-
)
52-
.expect("should save dependencies success");
51+
);
5352

5453
module_graph::save_module_graph(
5554
module_graph_partial,
@@ -59,14 +58,15 @@ impl MakeOccasion {
5958
&self.context,
6059
);
6160

62-
meta::save_meta(make_failed_dependencies, make_failed_module, &self.storage)
63-
.expect("should save make meta");
61+
meta::save_meta(make_failed_dependencies, make_failed_module, &self.storage);
6462
}
6563

6664
#[tracing::instrument(name = "MakeOccasion::recovery", skip_all)]
67-
pub async fn recovery(&self) -> Result<MakeArtifact, DeserializeError> {
65+
pub async fn recovery(&self) -> Result<MakeArtifact> {
6866
let mut artifact = MakeArtifact::default();
6967

68+
// TODO can call recovery with multi thread
69+
// TODO return DeserializeError not panic
7070
let (file_dependencies, context_dependencies, missing_dependencies, build_dependencies) =
7171
dependencies::recovery_dependencies_info(&self.storage).await?;
7272
artifact.file_dependencies = file_dependencies;

crates/rspack_core/src/cache/persistent/occasion/make/module_graph.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use rayon::prelude::*;
44
use rspack_cacheable::{
55
cacheable, from_bytes, to_bytes,
66
with::{AsOption, AsTuple2, AsVec, Inline},
7-
DeserializeError, SerializeError,
7+
SerializeError,
88
};
99
use rspack_collections::IdentifierSet;
10+
use rspack_error::Result;
1011
use rustc_hash::FxHashSet as HashSet;
1112

1213
use super::Storage;
@@ -125,11 +126,11 @@ pub fn save_module_graph(
125126
pub async fn recovery_module_graph(
126127
storage: &Arc<dyn Storage>,
127128
context: &CacheableContext,
128-
) -> Result<(ModuleGraphPartial, HashSet<BuildDependency>), DeserializeError> {
129+
) -> Result<(ModuleGraphPartial, HashSet<BuildDependency>)> {
129130
let mut need_check_dep = vec![];
130131
let mut partial = ModuleGraphPartial::default();
131132
let mut mg = ModuleGraph::new(vec![], Some(&mut partial));
132-
for (_, v) in storage.load(SCOPE).await.unwrap_or_default() {
133+
for (_, v) in storage.load(SCOPE).await? {
133134
let mut node: Node =
134135
from_bytes(&v, context).expect("unexpected module graph deserialize failed");
135136
for (dep, parent_block) in node.dependencies {

0 commit comments

Comments
 (0)