Don't use separate temp dir for query jsons (2) (#2803)

* Don't use temp dir for query jsons

Fixes #2663

* Return early when exclusive create fails

* Use atomic-file-write for writing query data
This commit is contained in:
Matt Fellenz
2023-10-17 11:41:30 -07:00
committed by GitHub
parent f93bbe87be
commit b16fbebf2f
5 changed files with 13 additions and 48 deletions

View File

@@ -150,31 +150,22 @@ where
}
}
pub(super) fn save_in(
&self,
dir: impl AsRef<Path>,
tmp_dir: impl AsRef<Path>,
) -> crate::Result<()> {
// Output to a temporary file first, then move it atomically to avoid clobbering
// other invocations trying to write to the same path.
pub(super) fn save_in(&self, dir: impl AsRef<Path>) -> crate::Result<()> {
let path = dir.as_ref().join(format!("query-{}.json", self.hash));
let mut file = atomic_write_file::AtomicWriteFile::open(&path)
.map_err(|err| format!("failed to open the temporary file: {err:?}"))?;
// Use a temp directory inside the workspace to avoid potential issues
// with persisting the file across filesystems.
let mut tmp_file = tempfile::NamedTempFile::new_in(tmp_dir)
.map_err(|err| format!("failed to create query file: {err:?}"))?;
serde_json::to_writer_pretty(tmp_file.as_file_mut(), self)
serde_json::to_writer_pretty(file.as_file_mut(), self)
.map_err(|err| format!("failed to serialize query data to file: {err:?}"))?;
// Ensure there is a newline at the end of the JSON file to avoid accidental modification by IDE
// and make github diff tool happier
tmp_file
.as_file_mut()
// Ensure there is a newline at the end of the JSON file to avoid
// accidental modification by IDE and make github diff tool happier.
file.as_file_mut()
.write_all(b"\n")
.map_err(|err| format!("failed to append a newline to file: {err:?}"))?;
tmp_file
.persist(dir.as_ref().join(format!("query-{}.json", self.hash)))
.map_err(|err| format!("failed to move query file: {err:?}"))?;
file.commit()
.map_err(|err| format!("failed to commit the query data to {path:?}: {err:?}"))?;
Ok(())
}

View File

@@ -356,19 +356,6 @@ where
if let Ok(dir) = env("SQLX_OFFLINE_DIR") {
let path = PathBuf::from(&dir);
// Prefer SQLX_TMP if set explicitly.
// Otherwise fallback to CARGO_TARGET_DIR and then the standard target directory.
let tmp_dir = if let Ok(tmp_dir) = env("SQLX_TMP") {
PathBuf::from(tmp_dir)
} else if let Ok(target_dir) = env("CARGO_TARGET_DIR") {
PathBuf::from(target_dir)
} else {
let tmp_target = PathBuf::from("./target/sqlx");
fs::create_dir_all(&tmp_target)
.map_err(|e| format!("Error creating cache directory: {e:?}"))?;
tmp_target
};
match fs::metadata(&path) {
Err(e) => {
if e.kind() != io::ErrorKind::NotFound {
@@ -387,7 +374,7 @@ where
}
// .sqlx exists and is a directory, store data.
data.save_in(path, tmp_dir)?;
data.save_in(path)?;
}
}
}