Skip to content

Commit 8f30dd3

Browse files
committed
Rename write_policy to write_error_policy
1 parent 6facb61 commit 8f30dd3

4 files changed

Lines changed: 55 additions & 52 deletions

File tree

docs/MultiLevel.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export SCCACHE_MULTILEVEL_CHAIN="disk,redis,s3"
132132

133133
### Write Policy Configuration
134134

135-
Control how sccache handles write failures across cache levels using `SCCACHE_MULTILEVEL_WRITE_POLICY`:
135+
Control how sccache handles write failures across cache levels using `SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY`:
136136

137137
**Available policies**:
138138
- **`ignore`** - Never fail on write errors, log warnings only (most permissive)
@@ -146,21 +146,21 @@ Control how sccache handles write failures across cache levels using `SCCACHE_MU
146146
**Example 1: Default Behavior (l0 policy)**
147147
```bash
148148
export SCCACHE_MULTILEVEL_CHAIN="disk,redis,s3"
149-
export SCCACHE_MULTILEVEL_WRITE_POLICY="l0" # or omit, it's the default
149+
export SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY="l0" # or omit, it's the default
150150
```
151151
Compilation succeeds if disk write succeeds. Redis/S3 failures are logged but don't block compilation. Ensures local cache is always populated. **Best for most use cases.**
152152

153153
**Example 2: Best Effort (ignore policy)**
154154
```bash
155155
export SCCACHE_MULTILEVEL_CHAIN="disk,redis,s3"
156-
export SCCACHE_MULTILEVEL_WRITE_POLICY="ignore"
156+
export SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY="ignore"
157157
```
158158
Compilation always succeeds, even if all writes fail. Write failures are logged as warnings. **Best for unstable cache backends** where you don't want cache issues blocking builds.
159159

160160
**Example 3: Strict Consistency (all policy)**
161161
```bash
162162
export SCCACHE_MULTILEVEL_CHAIN="disk,redis,s3"
163-
export SCCACHE_MULTILEVEL_WRITE_POLICY="all"
163+
export SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY="all"
164164
```
165165
Compilation succeeds only if all read-write levels succeed. Any write failure fails the compilation. **Best for critical environments** where cache consistency is mandatory.
166166

@@ -170,7 +170,7 @@ Any level configured as read-only (e.g., `SCCACHE_LOCAL_RW_MODE=READ_ONLY`) is a
170170

171171
```bash
172172
export SCCACHE_MULTILEVEL_CHAIN="disk,redis"
173-
export SCCACHE_MULTILEVEL_WRITE_POLICY="all"
173+
export SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY="all"
174174
export SCCACHE_LOCAL_RW_MODE="READ_ONLY" # Disk is read-only
175175
# Compilation succeeds if Redis write succeeds (disk is skipped)
176176
```
@@ -180,7 +180,7 @@ export SCCACHE_LOCAL_RW_MODE="READ_ONLY" # Disk is read-only
180180
```bash
181181
# Multi-level configuration
182182
export SCCACHE_MULTILEVEL_CHAIN="disk,redis,s3"
183-
export SCCACHE_MULTILEVEL_WRITE_POLICY="l0" # Default: fail only if disk fails
183+
export SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY="l0" # Default: fail only if disk fails
184184

185185
# Level 0: Disk cache
186186
export SCCACHE_DIR="/var/cache/sccache"
@@ -202,7 +202,7 @@ export SCCACHE_S3_USE_SSL="true"
202202
# ~/.config/sccache/config
203203
[cache.multilevel]
204204
chain = ["disk", "redis", "s3"]
205-
write_policy = "l0" # Optional: ignore, l0 (default), or all
205+
write_error_policy = "l0" # Optional: ignore, l0 (default), or all
206206

207207
[cache.disk]
208208
dir = "/var/cache/sccache"

src/cache/multilevel.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use crate::compiler::PreprocessorCacheEntry;
4747
feature = "cos"
4848
))]
4949
use crate::config::CacheType;
50-
use crate::config::{Config, PreprocessorCacheModeConfig, WritePolicy};
50+
use crate::config::{Config, PreprocessorCacheModeConfig, WriteErrorPolicy};
5151
use crate::errors::*;
5252

5353
/// Lock-free atomic counters for multi-level cache statistics.
@@ -307,7 +307,7 @@ impl MultiLevelStats {
307307
/// See docs/MultiLevel.md for details.
308308
pub struct MultiLevelStorage {
309309
levels: Vec<Arc<dyn Storage>>,
310-
write_policy: WritePolicy,
310+
write_error_policy: WriteErrorPolicy,
311311
/// Lock-free atomic statistics per level
312312
atomic_stats: Vec<Arc<AtomicLevelStats>>,
313313
/// Base directories for path normalization, propagated to compiler pipeline
@@ -333,17 +333,20 @@ impl MultiLevelStorage {
333333
/// Levels are checked in order (L0, L1, L2, ...) during reads.
334334
/// All levels receive writes in parallel.
335335
pub fn new(levels: Vec<Arc<dyn Storage>>) -> Self {
336-
Self::with_write_policy(levels, WritePolicy::default())
336+
Self::with_write_error_policy(levels, WriteErrorPolicy::default())
337337
}
338338

339339
/// Create a new multi-level storage with explicit write policy.
340-
pub fn with_write_policy(levels: Vec<Arc<dyn Storage>>, write_policy: WritePolicy) -> Self {
340+
pub fn with_write_error_policy(
341+
levels: Vec<Arc<dyn Storage>>,
342+
write_error_policy: WriteErrorPolicy,
343+
) -> Self {
341344
let atomic_stats = AtomicLevelStats::from_levels(&levels);
342345
let basedirs = Self::collect_basedirs(&levels);
343346

344347
MultiLevelStorage {
345348
levels,
346-
write_policy,
349+
write_error_policy,
347350
atomic_stats,
348351
basedirs,
349352
}
@@ -391,7 +394,7 @@ impl MultiLevelStorage {
391394
);
392395

393396
let levels = &ml_config.chain;
394-
let write_policy = ml_config.write_policy;
397+
let write_error_policy = ml_config.write_error_policy;
395398

396399
let mut storages: Vec<Arc<dyn Storage>> = Vec::new();
397400

@@ -508,9 +511,9 @@ impl MultiLevelStorage {
508511
storages.len()
509512
);
510513

511-
Ok(Some(MultiLevelStorage::with_write_policy(
514+
Ok(Some(MultiLevelStorage::with_write_error_policy(
512515
storages,
513-
write_policy,
516+
write_error_policy,
514517
)))
515518
}
516519

@@ -696,14 +699,14 @@ impl Storage for MultiLevelStorage {
696699
let data: Bytes = entry.finish()?.into();
697700
let key_str = key.to_string();
698701

699-
match self.write_policy {
700-
WritePolicy::Ignore => {
702+
match self.write_error_policy {
703+
WriteErrorPolicy::Ignore => {
701704
// Never fail, log warnings only
702705
self.write_remaining_levels_async(&key_str, &data, 0).await;
703706
Ok(Duration::ZERO)
704707
}
705708

706-
WritePolicy::L0 => {
709+
WriteErrorPolicy::L0 => {
707710
// Fail only if L0 write fails (unless L0 is read-only)
708711
if let Some(l0) = self.levels.first() {
709712
// Check if L0 is read-only before attempting write
@@ -731,7 +734,7 @@ impl Storage for MultiLevelStorage {
731734
Ok(Duration::ZERO)
732735
}
733736

734-
WritePolicy::All => {
737+
WriteErrorPolicy::All => {
735738
// Fail if any RW level fails
736739
use tokio::sync::mpsc;
737740
let (tx, mut rx) = mpsc::channel(self.levels.len());

src/cache/multilevel_test.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,9 +1143,9 @@ fn test_put_mode_ignore() {
11431143
let cache_l0 = Arc::new(FailingStorage);
11441144
let cache_l1 = Arc::new(FailingStorage);
11451145

1146-
let storage = MultiLevelStorage::with_write_policy(
1146+
let storage = MultiLevelStorage::with_write_error_policy(
11471147
vec![cache_l0 as Arc<dyn Storage>, cache_l1 as Arc<dyn Storage>],
1148-
WritePolicy::Ignore,
1148+
WriteErrorPolicy::Ignore,
11491149
);
11501150

11511151
runtime.block_on(async {
@@ -1154,7 +1154,7 @@ fn test_put_mode_ignore() {
11541154

11551155
assert!(
11561156
result.is_ok(),
1157-
"WritePolicy::Ignore should never fail, even when all levels error"
1157+
"WriteErrorPolicy::Ignore should never fail, even when all levels error"
11581158
);
11591159
});
11601160
}
@@ -1171,9 +1171,9 @@ fn test_put_mode_l0_fails_on_error() {
11711171
let cache_l0 = Arc::new(FailingStorage);
11721172
let cache_l1 = Arc::new(InMemoryStorage::new());
11731173

1174-
let storage = MultiLevelStorage::with_write_policy(
1174+
let storage = MultiLevelStorage::with_write_error_policy(
11751175
vec![cache_l0 as Arc<dyn Storage>, cache_l1 as Arc<dyn Storage>],
1176-
WritePolicy::L0,
1176+
WriteErrorPolicy::L0,
11771177
);
11781178

11791179
runtime.block_on(async {
@@ -1182,7 +1182,7 @@ fn test_put_mode_l0_fails_on_error() {
11821182

11831183
assert!(
11841184
result.is_err(),
1185-
"WritePolicy::L0 should fail when L0 write fails"
1185+
"WriteErrorPolicy::L0 should fail when L0 write fails"
11861186
);
11871187
let err_msg = result.unwrap_err().to_string();
11881188
assert!(
@@ -1205,9 +1205,9 @@ fn test_put_mode_l0_succeeds_if_l0_ok() {
12051205
let cache_l0 = Arc::new(InMemoryStorage::new());
12061206
let cache_l1 = Arc::new(FailingStorage);
12071207

1208-
let storage = MultiLevelStorage::with_write_policy(
1208+
let storage = MultiLevelStorage::with_write_error_policy(
12091209
vec![cache_l0 as Arc<dyn Storage>, cache_l1 as Arc<dyn Storage>],
1210-
WritePolicy::L0,
1210+
WriteErrorPolicy::L0,
12111211
);
12121212

12131213
runtime.block_on(async {
@@ -1216,7 +1216,7 @@ fn test_put_mode_l0_succeeds_if_l0_ok() {
12161216

12171217
assert!(
12181218
result.is_ok(),
1219-
"WritePolicy::L0 should succeed when L0 succeeds, even if L1+ fails"
1219+
"WriteErrorPolicy::L0 should succeed when L0 succeeds, even if L1+ fails"
12201220
);
12211221
});
12221222
}
@@ -1233,9 +1233,9 @@ fn test_put_mode_all_fails_on_any_error() {
12331233
let cache_l0 = Arc::new(InMemoryStorage::new());
12341234
let cache_l1 = Arc::new(FailingStorage);
12351235

1236-
let storage = MultiLevelStorage::with_write_policy(
1236+
let storage = MultiLevelStorage::with_write_error_policy(
12371237
vec![cache_l0 as Arc<dyn Storage>, cache_l1 as Arc<dyn Storage>],
1238-
WritePolicy::All,
1238+
WriteErrorPolicy::All,
12391239
);
12401240

12411241
runtime.block_on(async {
@@ -1247,7 +1247,7 @@ fn test_put_mode_all_fails_on_any_error() {
12471247

12481248
assert!(
12491249
result.is_err(),
1250-
"WritePolicy::All should fail when any RW level fails"
1250+
"WriteErrorPolicy::All should fail when any RW level fails"
12511251
);
12521252
});
12531253
}
@@ -1264,12 +1264,12 @@ fn test_put_mode_all_succeeds_when_all_ok() {
12641264
let cache_l0 = Arc::new(InMemoryStorage::new());
12651265
let cache_l1 = Arc::new(InMemoryStorage::new());
12661266

1267-
let storage = MultiLevelStorage::with_write_policy(
1267+
let storage = MultiLevelStorage::with_write_error_policy(
12681268
vec![
12691269
cache_l0.clone() as Arc<dyn Storage>,
12701270
cache_l1.clone() as Arc<dyn Storage>,
12711271
],
1272-
WritePolicy::All,
1272+
WriteErrorPolicy::All,
12731273
);
12741274

12751275
runtime.block_on(async {
@@ -1281,7 +1281,7 @@ fn test_put_mode_all_succeeds_when_all_ok() {
12811281

12821282
assert!(
12831283
result.is_ok(),
1284-
"WritePolicy::All should succeed when all levels succeed"
1284+
"WriteErrorPolicy::All should succeed when all levels succeed"
12851285
);
12861286

12871287
// Verify both levels have the data
@@ -1309,13 +1309,13 @@ fn test_put_mode_all_skips_readonly() {
13091309
let cache_l1 = Arc::new(ReadOnlyStorage(Arc::new(InMemoryStorage::new())));
13101310
let cache_l2 = Arc::new(InMemoryStorage::new());
13111311

1312-
let storage = MultiLevelStorage::with_write_policy(
1312+
let storage = MultiLevelStorage::with_write_error_policy(
13131313
vec![
13141314
cache_l0.clone() as Arc<dyn Storage>,
13151315
cache_l1 as Arc<dyn Storage>,
13161316
cache_l2.clone() as Arc<dyn Storage>,
13171317
],
1318-
WritePolicy::All,
1318+
WriteErrorPolicy::All,
13191319
);
13201320

13211321
runtime.block_on(async {
@@ -1327,7 +1327,7 @@ fn test_put_mode_all_skips_readonly() {
13271327

13281328
assert!(
13291329
result.is_ok(),
1330-
"WritePolicy::All should succeed when read-only levels are skipped"
1330+
"WriteErrorPolicy::All should succeed when read-only levels are skipped"
13311331
);
13321332

13331333
// Verify writable levels have the data

src/config.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use crate::errors::*;
4040
/// Defines how the multi-level cache handles write failures.
4141
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
4242
#[serde(rename_all = "lowercase")]
43-
pub enum WritePolicy {
43+
pub enum WriteErrorPolicy {
4444
/// Never fail on write errors - log warnings only (most permissive)
4545
Ignore,
4646
/// Fail only if L0 write fails (default - balances reliability and performance)
@@ -50,14 +50,14 @@ pub enum WritePolicy {
5050
All,
5151
}
5252

53-
impl FromStr for WritePolicy {
53+
impl FromStr for WriteErrorPolicy {
5454
type Err = anyhow::Error;
5555

5656
fn from_str(s: &str) -> Result<Self> {
5757
match s.to_lowercase().as_str() {
58-
"ignore" => Ok(WritePolicy::Ignore),
59-
"l0" => Ok(WritePolicy::L0),
60-
"all" => Ok(WritePolicy::All),
58+
"ignore" => Ok(WriteErrorPolicy::Ignore),
59+
"l0" => Ok(WriteErrorPolicy::L0),
60+
"all" => Ok(WriteErrorPolicy::All),
6161
_ => Err(anyhow!(
6262
"Invalid write policy '{}'. Valid values: ignore, l0, all",
6363
s
@@ -66,12 +66,12 @@ impl FromStr for WritePolicy {
6666
}
6767
}
6868

69-
impl fmt::Display for WritePolicy {
69+
impl fmt::Display for WriteErrorPolicy {
7070
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7171
match self {
72-
WritePolicy::Ignore => write!(f, "ignore"),
73-
WritePolicy::L0 => write!(f, "l0"),
74-
WritePolicy::All => write!(f, "all"),
72+
WriteErrorPolicy::Ignore => write!(f, "ignore"),
73+
WriteErrorPolicy::L0 => write!(f, "l0"),
74+
WriteErrorPolicy::All => write!(f, "all"),
7575
}
7676
}
7777
}
@@ -84,7 +84,7 @@ pub struct MultiLevelConfig {
8484
pub chain: Vec<String>,
8585
/// Write failure handling policy
8686
#[serde(default)]
87-
pub write_policy: WritePolicy,
87+
pub write_error_policy: WriteErrorPolicy,
8888
}
8989

9090
static CACHED_CONFIG_PATH: LazyLock<PathBuf> = LazyLock::new(CachedConfig::file_config_path);
@@ -1138,14 +1138,14 @@ fn config_from_env() -> Result<EnvConfig> {
11381138
let multilevel = if let Ok(chain_str) = env::var("SCCACHE_MULTILEVEL_CHAIN") {
11391139
let chain: Vec<String> = chain_str.split(',').map(|s| s.trim().to_string()).collect();
11401140

1141-
let write_policy = env::var("SCCACHE_MULTILEVEL_WRITE_POLICY")
1141+
let write_error_policy = env::var("SCCACHE_MULTILEVEL_WRITE_ERROR_POLICY")
11421142
.ok()
1143-
.and_then(|s| s.parse::<WritePolicy>().ok())
1143+
.and_then(|s| s.parse::<WriteErrorPolicy>().ok())
11441144
.unwrap_or_default();
11451145

11461146
Some(MultiLevelConfig {
11471147
chain,
1148-
write_policy,
1148+
write_error_policy,
11491149
})
11501150
} else {
11511151
None
@@ -2831,7 +2831,7 @@ fn test_get_cache_levels_invalid_level() {
28312831
let configs = CacheConfigs {
28322832
multilevel: Some(MultiLevelConfig {
28332833
chain: vec!["unknown_cache".to_string()],
2834-
write_policy: WritePolicy::default(),
2834+
write_error_policy: WriteErrorPolicy::default(),
28352835
}),
28362836
..Default::default()
28372837
};
@@ -2851,7 +2851,7 @@ fn test_get_cache_levels_missing_config() {
28512851
let configs = CacheConfigs {
28522852
multilevel: Some(MultiLevelConfig {
28532853
chain: vec!["s3".to_string()],
2854-
write_policy: WritePolicy::default(),
2854+
write_error_policy: WriteErrorPolicy::default(),
28552855
}),
28562856
..Default::default()
28572857
};

0 commit comments

Comments
 (0)