Skip to content

Commit baf9610

Browse files
committed
Add a timeout to cache lookups
This should help ensure that we don't wait *too* long for the cache to respond (for example on an excessively slow network) and time out the server unnecessarily.
1 parent ca2f8fc commit baf9610

2 files changed

Lines changed: 55 additions & 12 deletions

File tree

src/compiler/compiler.rs

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use std::time::{
5353
Instant,
5454
};
5555
use tempdir::TempDir;
56+
use tokio_core::reactor::{Handle, Timeout};
5657

5758
use errors::*;
5859

@@ -174,6 +175,8 @@ pub enum MissType {
174175
Normal,
175176
/// Cache lookup was overridden, recompilation was forced.
176177
ForcedRecache,
178+
/// Cache took too long to respond.
179+
TimedOut,
177180
}
178181

179182
/// Information about a successful cache write.
@@ -298,7 +301,8 @@ impl Compiler {
298301
parsed_args: &ParsedArguments,
299302
cwd: &str,
300303
cache_control: CacheControl,
301-
pool: &CpuPool)
304+
pool: &CpuPool,
305+
handle: &Handle)
302306
-> SFuture<(CompileResult, process::Output)>
303307
where T: CommandCreatorSync
304308
{
@@ -319,6 +323,7 @@ impl Compiler {
319323
let storage = storage.clone();
320324
let pool = pool.clone();
321325
let creator = creator.clone();
326+
let handle = handle.clone();
322327

323328
Box::new(result.and_then(move |preprocessor_result| -> SFuture<_> {
324329
// If the preprocessor failed, just return that result.
@@ -355,6 +360,20 @@ impl Compiler {
355360
storage.get(&key)
356361
};
357362

363+
// Wait at most a minute for the cache to respond before we forge
364+
// ahead ourselves with a compilation.
365+
let timeout = Duration::new(60, 0);
366+
let timeout = Timeout::new(timeout, &handle).into_future().flatten();
367+
368+
let cache_status = cache_status.map(Some);
369+
let timeout = timeout.map(|_| None).chain_err(|| "timeout error");
370+
let cache_status = cache_status.select(timeout).then(|r| {
371+
match r {
372+
Ok((a, _other)) => Ok(a),
373+
Err((e, _other)) => Err(e),
374+
}
375+
});
376+
358377
Box::new(cache_status.and_then(move |result| {
359378
let duration = start.elapsed();
360379
let pwd = Path::new(&cwd);
@@ -363,7 +382,7 @@ impl Compiler {
363382
.collect::<HashMap<_, _>>();
364383

365384
let miss_type = match result {
366-
Cache::Hit(mut entry) => {
385+
Some(Cache::Hit(mut entry)) => {
367386
debug!("[{}]: Cache hit!", parsed_args.output_file());
368387
let mut stdout = io::Cursor::new(vec!());
369388
let mut stderr = io::Cursor::new(vec!());
@@ -386,14 +405,18 @@ impl Compiler {
386405
(result, output)
387406
})) as SFuture<_>
388407
}
389-
Cache::Miss => {
408+
Some(Cache::Miss) => {
390409
debug!("[{}]: Cache miss!", parsed_args.output_file());
391410
MissType::Normal
392411
}
393-
Cache::Recache => {
412+
Some(Cache::Recache) => {
394413
debug!("[{}]: Cache recache!", parsed_args.output_file());
395414
MissType::ForcedRecache
396415
}
416+
None => {
417+
debug!("[{}]: Cache timed out!", parsed_args.output_file());
418+
MissType::TimedOut
419+
}
397420
};
398421
me.compile(&creator,
399422
preprocessor_result,
@@ -662,6 +685,7 @@ mod test {
662685
use std::time::Duration;
663686
use std::usize;
664687
use test::utils::*;
688+
use tokio_core::reactor::Core;
665689

666690
#[test]
667691
fn test_detect_compiler_kind_gcc() {
@@ -742,6 +766,8 @@ mod test {
742766
let creator = new_creator();
743767
let f = TestFixture::new();
744768
let pool = CpuPool::new(1);
769+
let core = Core::new().unwrap();
770+
let handle = core.handle();
745771
let storage = DiskCache::new(&f.tempdir.path().join("cache"),
746772
usize::MAX,
747773
&pool);
@@ -778,7 +804,8 @@ mod test {
778804
&parsed_args,
779805
cwd,
780806
CacheControl::Default,
781-
&pool).wait().unwrap();
807+
&pool,
808+
&handle).wait().unwrap();
782809
// Ensure that the object file was created.
783810
assert_eq!(true, fs::metadata(&obj).and_then(|m| Ok(m.len() > 0)).unwrap());
784811
match cached {
@@ -802,7 +829,8 @@ mod test {
802829
&parsed_args,
803830
cwd,
804831
CacheControl::Default,
805-
&pool).wait().unwrap();
832+
&pool,
833+
&handle).wait().unwrap();
806834
// Ensure that the object file was created.
807835
assert_eq!(true, fs::metadata(&obj).and_then(|m| Ok(m.len() > 0)).unwrap());
808836
assert_eq!(CompileResult::CacheHit(Duration::new(0, 0)), cached);
@@ -818,6 +846,8 @@ mod test {
818846
let creator = new_creator();
819847
let f = TestFixture::new();
820848
let pool = CpuPool::new(1);
849+
let core = Core::new().unwrap();
850+
let handle = core.handle();
821851
let storage = DiskCache::new(&f.tempdir.path().join("cache"),
822852
usize::MAX,
823853
&pool);
@@ -854,7 +884,8 @@ mod test {
854884
&parsed_args,
855885
cwd,
856886
CacheControl::Default,
857-
&pool).wait().unwrap();
887+
&pool,
888+
&handle).wait().unwrap();
858889
// Ensure that the object file was created.
859890
assert_eq!(true, fs::metadata(&obj).and_then(|m| Ok(m.len() > 0)).unwrap());
860891
match cached {
@@ -879,7 +910,8 @@ mod test {
879910
&parsed_args,
880911
cwd,
881912
CacheControl::Default,
882-
&pool).wait().unwrap();
913+
&pool,
914+
&handle).wait().unwrap();
883915
// Ensure that the object file was created.
884916
assert_eq!(true, fs::metadata(&obj).and_then(|m| Ok(m.len() > 0)).unwrap());
885917
assert_eq!(CompileResult::CacheHit(Duration::new(0, 0)), cached);
@@ -895,6 +927,8 @@ mod test {
895927
let creator = new_creator();
896928
let f = TestFixture::new();
897929
let pool = CpuPool::new(1);
930+
let core = Core::new().unwrap();
931+
let handle = core.handle();
898932
let storage = DiskCache::new(&f.tempdir.path().join("cache"),
899933
usize::MAX,
900934
&pool);
@@ -935,7 +969,8 @@ mod test {
935969
&parsed_args,
936970
cwd,
937971
CacheControl::Default,
938-
&pool).wait().unwrap();
972+
&pool,
973+
&handle).wait().unwrap();
939974
// Ensure that the object file was created.
940975
assert_eq!(true, fs::metadata(&obj).and_then(|m| Ok(m.len() > 0)).unwrap());
941976
match cached {
@@ -956,7 +991,8 @@ mod test {
956991
&parsed_args,
957992
cwd,
958993
CacheControl::ForceRecache,
959-
&pool).wait().unwrap();
994+
&pool,
995+
&handle).wait().unwrap();
960996
// Ensure that the object file was created.
961997
assert_eq!(true, fs::metadata(&obj).and_then(|m| Ok(m.len() > 0)).unwrap());
962998
match cached {
@@ -978,6 +1014,8 @@ mod test {
9781014
let creator = new_creator();
9791015
let f = TestFixture::new();
9801016
let pool = CpuPool::new(1);
1017+
let core = Core::new().unwrap();
1018+
let handle = core.handle();
9811019
let storage = DiskCache::new(&f.tempdir.path().join("cache"),
9821020
usize::MAX,
9831021
&pool);
@@ -1002,7 +1040,8 @@ mod test {
10021040
&parsed_args,
10031041
cwd,
10041042
CacheControl::Default,
1005-
&pool).wait().unwrap();
1043+
&pool,
1044+
&handle).wait().unwrap();
10061045
assert_eq!(cached, CompileResult::Error);
10071046
assert_eq!(exit_status(1), res.status);
10081047
// Shouldn't get anything on stdout, since that would just be preprocessor spew!

src/server.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,8 @@ impl<C> SccacheService<C>
549549
&parsed_arguments,
550550
&cwd,
551551
cache_control,
552-
&self.pool);
552+
&self.pool,
553+
&self.handle);
553554
let me = self.clone();
554555
let task = result.then(move |result| {
555556
let mut res = ServerResponse::new();
@@ -575,6 +576,9 @@ impl<C> SccacheService<C>
575576
stats.cache_misses += 1;
576577
stats.forced_recaches += 1;
577578
}
579+
MissType::TimedOut => {
580+
stats.cache_misses += 1;
581+
}
578582
}
579583
stats.cache_read_miss_duration += duration;
580584
cache_write = Some(future);

0 commit comments

Comments
 (0)