git_lfs_transfer/config.rs
1use std::sync::Arc;
2use std::time::Duration;
3
4/// Optional URL transform applied to every action `href` returned by the
5/// batch endpoint before the transfer adapter dials it. Used to plumb
6/// `lfs.transfer.enablehrefrewrite` + `url.<base>.insteadOf` from the
7/// caller (which has the git-config context) down into the queue.
8pub type UrlRewriter = Arc<dyn Fn(&str) -> String + Send + Sync>;
9
10/// Tunables for the transfer queue.
11///
12/// Defaults aim at "sensible for a developer laptop on a corporate VPN" —
13/// not too aggressive on concurrency, generous retries for flaky links.
14/// Upstream Git LFS scales `concurrency` to CPU count (commit `aa08c37f`);
15/// we hard-code 8 for v0 and let callers override.
16#[derive(Clone)]
17pub struct TransferConfig {
18 /// Max number of concurrent in-flight transfers.
19 pub concurrency: usize,
20 /// Total attempts per object — including the first. So 3 means "try
21 /// once, then up to 2 retries".
22 pub max_attempts: u32,
23 /// Sleep before the first retry. Doubled before each subsequent retry,
24 /// capped at [`backoff_max`](Self::backoff_max).
25 pub initial_backoff: Duration,
26 /// Upper bound for exponential backoff between retries.
27 pub backoff_max: Duration,
28 /// Optional rewriter applied to every action URL before transfer.
29 /// `None` ⇒ use action URLs verbatim.
30 pub url_rewriter: Option<UrlRewriter>,
31}
32
33impl Default for TransferConfig {
34 fn default() -> Self {
35 Self {
36 concurrency: 8,
37 max_attempts: 3,
38 initial_backoff: Duration::from_millis(100),
39 backoff_max: Duration::from_secs(30),
40 url_rewriter: None,
41 }
42 }
43}
44
45impl std::fmt::Debug for TransferConfig {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 f.debug_struct("TransferConfig")
48 .field("concurrency", &self.concurrency)
49 .field("max_attempts", &self.max_attempts)
50 .field("initial_backoff", &self.initial_backoff)
51 .field("backoff_max", &self.backoff_max)
52 .field("url_rewriter", &self.url_rewriter.as_ref().map(|_| "<fn>"))
53 .finish()
54 }
55}