diff --git a/Cargo.lock b/Cargo.lock index 6f7a88f6a..01bfbdc4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backoff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721c249ab59cbc483ad4294c9ee2671835c1e43e9ffc277e6b4ecfef733cfdc5" +dependencies = [ + "instant", + "rand 0.7.3", +] + [[package]] name = "base64" version = "0.12.3" @@ -168,6 +178,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "chrono" version = "0.4.19" @@ -282,7 +298,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils", "lazy_static", "maybe-uninit", @@ -297,7 +313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 0.1.10", "lazy_static", ] @@ -414,7 +430,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -425,7 +441,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -492,6 +508,15 @@ dependencies = [ "unindent", ] +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "itertools" version = "0.9.0" @@ -539,6 +564,7 @@ dependencies = [ name = "jj-lib" version = "0.1.0" dependencies = [ + "backoff", "blake2", "byteorder", "bytes 1.0.0", @@ -593,7 +619,7 @@ checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" dependencies = [ "arrayvec", "bitflags", - "cfg-if", + "cfg-if 0.1.10", "ryu", "static_assertions", ] @@ -666,7 +692,7 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -1242,7 +1268,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand 0.7.3", "redox_syscall", @@ -1451,7 +1477,7 @@ version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "wasm-bindgen-macro", ] diff --git a/lib/Cargo.toml b/lib/Cargo.toml index fc1d585b5..f7db59dfc 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" protobuf-codegen-pure = "2.18.1" [dependencies] +backoff = "0.2.1" blake2 = "0.9.1" bytes = "1.0.0" byteorder = "1.3.4" diff --git a/lib/src/git_store.rs b/lib/src/git_store.rs index 4eef16093..e49e5c61c 100644 --- a/lib/src/git_store.rs +++ b/lib/src/git_store.rs @@ -27,6 +27,7 @@ use crate::store::{ ChangeId, Commit, CommitId, Conflict, ConflictId, ConflictPart, FileId, MillisSinceEpoch, Signature, Store, StoreError, StoreResult, SymlinkId, Timestamp, Tree, TreeId, TreeValue, }; +use backoff::{ExponentialBackoff, Operation}; const NOTES_REF: &str = "refs/notes/jj/commits"; const NOTES_REF_LOCK: &str = "refs/notes/jj/commits.lock"; @@ -316,7 +317,10 @@ impl Store for GitStore { // TODO: Include the extra commit data in commit headers instead of a ref. // Unfortunately, it doesn't seem like libgit2-rs supports that. Perhaps // we'll have to serialize/deserialize the commit data ourselves. - loop { + // It seems that libgit2 doesn't retry when .git/refs/notes/jj/commits.lock + // already exists, so we do the retrying ourselves. + // TODO: Report this to libgit2. + let mut try_write_note = || { let note_status = locked_repo.note( &committer, &committer, @@ -327,20 +331,21 @@ impl Store for GitStore { ); match note_status { Err(err) if err.message().contains(NOTES_REF_LOCK) => { - // It seems that libgit2 doesn't retry when .git/refs/notes/jj/commits.lock - // already exists. - // TODO: Report this to libgit2. - let retry_delay = Duration::from_millis(10); - std::thread::sleep(retry_delay); - } - Err(err) => { - return Err(StoreError::from(err)); - } - Ok(_) => { - break; + Err(backoff::Error::Transient(err)) } + Err(err) => Err(backoff::Error::Permanent(err)), + Ok(_) => Ok(()), } - } + }; + let mut backoff = ExponentialBackoff::default(); + backoff.initial_interval = Duration::from_millis(1); + backoff.max_elapsed_time = Some(Duration::from_secs(10)); + try_write_note + .retry(&mut backoff) + .map_err(|err| match err { + backoff::Error::Permanent(err) => err, + backoff::Error::Transient(err) => err, + })?; Ok(id) }