ok/jj
1
0
Fork 0
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:
Martin von Zweigbergk 2020-12-24 22:56:05 -08:00
parent 210405b21a
commit ddf8416d92
3 changed files with 53 additions and 21 deletions

42
Cargo.lock generated
View file

@ -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",
]

View file

@ -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"

View file

@ -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)
}