fix: handle cache body file not existing when using etag (#22931)

This commit is contained in:
David Sherret 2024-03-15 09:57:24 -04:00 committed by GitHub
parent dae162f738
commit 36e6e4a009
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 3 deletions

View File

@ -14,6 +14,7 @@ use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::UpdateGuard;
use deno_ast::MediaType;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::custom_error;
use deno_core::error::generic_error;
@ -372,6 +373,7 @@ impl FileFetcher {
}
async move {
let mut maybe_etag = maybe_etag;
let mut retried = false;
let result = loop {
let result = match fetch_once(
@ -388,9 +390,23 @@ impl FileFetcher {
{
FetchOnceResult::NotModified => {
let file = file_fetcher
.fetch_cached(&specifier, maybe_checksum, 10)?
.unwrap();
Ok(file)
.fetch_cached(&specifier, maybe_checksum.clone(), 10)?;
match file {
Some(file) => Ok(file),
None => {
// Someone may have deleted the body from the cache since
// it's currently stored in a separate file from the headers,
// so delete the etag and try again
if maybe_etag.is_some() {
debug!("Cache body not found. Trying again without etag.");
maybe_etag = None;
continue;
} else {
// should never happen
bail!("Your deno cache directory is in an unrecoverable state. Please delete it and try again.")
}
}
}
}
FetchOnceResult::Redirect(redirect_url, headers) => {
file_fetcher.http_cache.set(&specifier, headers, &[])?;

View File

@ -5137,3 +5137,36 @@ console.log(add(3, 4));
let output = test_context.new_command().args("run main.ts").run();
output.assert_matches_text("[WILDCARD]5\n7\n");
}
#[test]
fn run_etag_delete_source_cache() {
let test_context = TestContextBuilder::new()
.use_temp_cwd()
.use_http_server()
.build();
test_context
.temp_dir()
.write("main.ts", "import 'http://localhost:4545/etag_script.ts'");
test_context
.new_command()
.args("cache main.ts")
.run()
.skip_output_check();
// The cache is currently stored unideally in two files where one file has the headers
// and the other contains the body. An issue can happen with the etag header where the
// headers file exists, but the body was deleted. We need to get the cache to gracefully
// handle this scenario.
let deno_dir = test_context.deno_dir().path();
let etag_script_path = deno_dir.join("deps/http/localhost_PORT4545/26110db7d42c9bad32386735cbc05c301f83e4393963deb8da14fec3b4202a13");
assert!(etag_script_path.exists());
etag_script_path.remove_file();
test_context
.new_command()
.args("cache --reload --log-level=debug main.ts")
.run()
.assert_matches_text(
"[WILDCARD]Cache body not found. Trying again without etag.[WILDCARD]",
);
}