forked from mirrors/jj
git_store: use exponential backoff when retrying note-writing
I have never run into this being a problem in practice, but this change is a stepping stone for two things: 1. Using exponential backoff for other locks (in particular the working copy). 2. Making the Git store write a ref for conflict objects, so they don't get GC'd (I want to do that before even I start dogfooding).
This commit is contained in:
parent
210405b21a
commit
ddf8416d92
3 changed files with 53 additions and 21 deletions
42
Cargo.lock
generated
42
Cargo.lock
generated
|
@ -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",
|
||||
]
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue