Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

use xxhash for asset manifest #1221

Merged
merged 1 commit into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ clap = "2.32.0"
cloudflare = "0.6.4"
config = "0.10.1"
console = "0.9.1"
data-encoding = "2.1.2"
dirs = "1.0.5"
env_logger = "0.6.1"
exitfailure = "0.5.1"
Expand All @@ -48,7 +47,6 @@ reqwest = { version = "0.10.1", features = ["blocking", "json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.39"
serde_with = "1.3.1"
sha2 = "0.8.0"
tempfile = "3.1.0"
term_size = "0.3"
text_io = "0.1.7"
Expand All @@ -59,6 +57,7 @@ url = "2.1.0"
uuid = { version = "0.8", features = ["v4"] }
which = "2.0.1"
ws = "0.9.0"
twox-hash = "1.5.0"

[dev-dependencies]
assert_cmd = "0.11.1"
Expand Down
33 changes: 19 additions & 14 deletions src/commands/kv/bucket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ pub use upload::upload_files;

use std::ffi::OsString;
use std::fs;
use std::hash::Hasher;
use std::path::Path;

use data_encoding::HEXLOWER;
use failure::format_err;
use ignore::overrides::{Override, OverrideBuilder};
use ignore::{Walk, WalkBuilder};
use indicatif::{ProgressBar, ProgressStyle};
use sha2::{Digest, Sha256};
use twox_hash::XxHash64;

use cloudflare::endpoints::workerskv::write_bulk::KeyValuePair;

Expand Down Expand Up @@ -197,10 +197,15 @@ pub fn generate_path_and_key(
let relative_path = path.strip_prefix(directory).unwrap();

let url_safe_path = generate_url_safe_path(relative_path)?;

let path_with_hash = if let Some(value) = value {
let digest = get_digest(value)?;

let digest = get_digest(value);
// it is ok to truncate the digest here because
// we also include the file name in the asset manifest key
//
// the most important thing here is to detect changes
// of a single file to invalidate the cache and
// it's impossible to serve two different files with the same name
let digest = digest[0..10].to_string();
generate_path_with_hash(relative_path, digest)?
} else {
url_safe_path.to_owned()
Expand All @@ -209,12 +214,13 @@ pub fn generate_path_and_key(
Ok((url_safe_path, path_with_hash))
}

fn get_digest(value: String) -> Result<String, failure::Error> {
let mut hasher = Sha256::new();
hasher.input(value);
let digest = hasher.result();
let hex_digest = HEXLOWER.encode(digest.as_ref())[0..10].to_string();
Ok(hex_digest)
fn get_digest(value: String) -> String {
let value = value.as_bytes();
let mut hasher = XxHash64::default();
hasher.write(value);
let digest = hasher.finish();
// encode u64 as hexadecimal to save space and information
format!("{:x}", digest)
}

// Assumes that `path` is a file (called from a match branch for path.is_file())
Expand Down Expand Up @@ -473,7 +479,7 @@ mod tests {
#[test]
fn it_inserts_hash_before_extension() {
let value = "<h1>Hello World!</h1>";
let hashed_value = get_digest(String::from(value)).unwrap();
let hashed_value = get_digest(String::from(value));

let path = PathBuf::from("path").join("to").join("asset.html");
let actual_path_with_hash =
Expand All @@ -487,7 +493,7 @@ mod tests {
#[test]
fn it_inserts_hash_without_extension() {
let value = "<h1>Hello World!</h1>";
let hashed_value = get_digest(String::from(value)).unwrap();
let hashed_value = get_digest(String::from(value));

let path = PathBuf::from("path").join("to").join("asset");
let actual_path_with_hash =
Expand Down Expand Up @@ -525,7 +531,6 @@ mod tests {
let directory = Path::new("./build");
let value = Some("<h1>Hello World!</h1>".to_string());
let (path, key) = generate_path_and_key(path, directory, value).unwrap();

let expected_path = "path/to/asset.ext".to_string();
let expected_key_regex = Regex::new(r"^path/to/asset\.[0-9a-f]{10}\.ext").unwrap();

Expand Down
1 change: 0 additions & 1 deletion src/commands/kv/bucket/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ pub fn upload_files(
} else {
None
};

while !(pairs.is_empty() && key_value_batch.is_empty()) {
if pairs.is_empty() {
// Last batch to upload
Expand Down