Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
httpd: Add a cache for `/tree`
xphoniex committed 2 years ago
commit 8a61aece01fedbda0ff8aae2ce58f823ce787348
parent b1f174817cbacfc120572da60f64569665812578
8 files changed +169 -88
modified Cargo.lock
@@ -50,6 +50,17 @@ dependencies = [
]

[[package]]
+
name = "ahash"
+
version = "0.8.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
+
dependencies = [
+
 "cfg-if",
+
 "once_cell",
+
 "version_check",
+
]
+

+
[[package]]
name = "aho-corasick"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -177,13 +188,13 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"

[[package]]
name = "async-trait"
-
version = "0.1.69"
+
version = "0.1.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7"
+
checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]

[[package]]
@@ -499,9 +510,9 @@ dependencies = [

[[package]]
name = "const-oid"
-
version = "0.9.3"
+
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6340df57935414636969091153f35f68d9f00bbc8fb4a9c6054706c213e6c6bc"
+
checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"

[[package]]
name = "core-foundation-sys"
@@ -511,9 +522,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"

[[package]]
name = "cpufeatures"
-
version = "0.2.8"
+
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
+
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [
 "libc",
]
@@ -576,16 +587,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df"

[[package]]
-
name = "ctor"
-
version = "0.1.26"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
-
dependencies = [
-
 "quote",
-
 "syn 1.0.109",
-
]
-

-
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -802,9 +803,9 @@ dependencies = [

[[package]]
name = "equivalent"
-
version = "1.0.0"
+
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
+
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"

[[package]]
name = "errno"
@@ -1053,7 +1054,16 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
-
 "ahash",
+
 "ahash 0.7.6",
+
]
+

+
[[package]]
+
name = "hashbrown"
+
version = "0.13.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
+
dependencies = [
+
 "ahash 0.8.3",
]

[[package]]
@@ -1098,9 +1108,9 @@ dependencies = [

[[package]]
name = "hermit-abi"
-
version = "0.3.1"
+
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"

[[package]]
name = "hmac"
@@ -1269,7 +1279,7 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
-
 "hermit-abi 0.3.1",
+
 "hermit-abi 0.3.2",
 "libc",
 "windows-sys",
]
@@ -1288,12 +1298,12 @@ dependencies = [

[[package]]
name = "is-terminal"
-
version = "0.4.8"
+
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb"
+
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
-
 "hermit-abi 0.3.1",
-
 "rustix 0.38.2",
+
 "hermit-abi 0.3.2",
+
 "rustix 0.38.4",
 "windows-sys",
]

@@ -1458,12 +1468,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"

[[package]]
+
name = "lru"
+
version = "0.10.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670"
+
dependencies = [
+
 "hashbrown 0.13.2",
+
]
+

+
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
-
 "regex-automata",
+
 "regex-automata 0.1.10",
]

[[package]]
@@ -1634,7 +1653,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
-
 "hermit-abi 0.3.1",
+
 "hermit-abi 0.3.2",
 "libc",
]

@@ -1666,15 +1685,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"

[[package]]
-
name = "output_vt100"
-
version = "0.1.3"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
-
dependencies = [
-
 "winapi",
-
]
-

-
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1761,7 +1771,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]

[[package]]
@@ -1832,13 +1842,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"

[[package]]
name = "pretty_assertions"
-
version = "1.3.0"
+
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
+
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
-
 "ctor",
 "diff",
-
 "output_vt100",
 "yansi",
]

@@ -1868,9 +1876,9 @@ dependencies = [

[[package]]
name = "proc-macro2"
-
version = "1.0.63"
+
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
+
checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"
dependencies = [
 "unicode-ident",
]
@@ -2067,6 +2075,7 @@ dependencies = [
 "flate2",
 "hyper",
 "lexopt",
+
 "lru",
 "nonempty 0.8.1",
 "pretty_assertions",
 "radicle",
@@ -2078,7 +2087,7 @@ dependencies = [
 "serde_json",
 "tempfile",
 "thiserror",
-
 "time 0.3.22",
+
 "time 0.3.23",
 "tokio",
 "tower",
 "tower-http",
@@ -2309,13 +2318,14 @@ dependencies = [

[[package]]
name = "regex"
-
version = "1.8.4"
+
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [
 "aho-corasick",
 "memchr",
-
 "regex-syntax 0.7.2",
+
 "regex-automata 0.3.2",
+
 "regex-syntax 0.7.4",
]

[[package]]
@@ -2328,6 +2338,17 @@ dependencies = [
]

[[package]]
+
name = "regex-automata"
+
version = "0.3.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf"
+
dependencies = [
+
 "aho-corasick",
+
 "memchr",
+
 "regex-syntax 0.7.4",
+
]
+

+
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2335,9 +2356,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"

[[package]]
name = "regex-syntax"
-
version = "0.7.2"
+
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"

[[package]]
name = "rfc6979"
@@ -2379,9 +2400,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"

[[package]]
name = "rustix"
-
version = "0.37.22"
+
version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c"
+
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [
 "bitflags 1.3.2",
 "errno",
@@ -2393,9 +2414,9 @@ dependencies = [

[[package]]
name = "rustix"
-
version = "0.38.2"
+
version = "0.38.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4"
+
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
dependencies = [
 "bitflags 2.3.3",
 "errno",
@@ -2453,29 +2474,29 @@ dependencies = [

[[package]]
name = "serde"
-
version = "1.0.166"
+
version = "1.0.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8"
+
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
dependencies = [
 "serde_derive",
]

[[package]]
name = "serde_derive"
-
version = "1.0.166"
+
version = "1.0.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6"
+
checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]

[[package]]
name = "serde_json"
-
version = "1.0.99"
+
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
+
checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed"
dependencies = [
 "indexmap 2.0.0",
 "itoa",
@@ -2485,9 +2506,9 @@ dependencies = [

[[package]]
name = "serde_path_to_error"
-
version = "0.1.12"
+
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0b1b6471d7496b051e03f1958802a73f88b947866f5146f329e47e36554f4e55"
+
checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a"
dependencies = [
 "itoa",
 "serde",
@@ -2610,9 +2631,9 @@ dependencies = [

[[package]]
name = "smallvec"
-
version = "1.10.0"
+
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"

[[package]]
name = "smawk"
@@ -2769,9 +2790,9 @@ dependencies = [

[[package]]
name = "syn"
-
version = "2.0.23"
+
version = "2.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737"
+
checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2"
dependencies = [
 "proc-macro2",
 "quote",
@@ -2805,7 +2826,7 @@ dependencies = [
 "cfg-if",
 "fastrand",
 "redox_syscall 0.3.5",
-
 "rustix 0.37.22",
+
 "rustix 0.37.23",
 "windows-sys",
]

@@ -2846,22 +2867,22 @@ dependencies = [

[[package]]
name = "thiserror"
-
version = "1.0.40"
+
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+
checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
dependencies = [
 "thiserror-impl",
]

[[package]]
name = "thiserror-impl"
-
version = "1.0.40"
+
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+
checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]

[[package]]
@@ -2887,9 +2908,9 @@ dependencies = [

[[package]]
name = "time"
-
version = "0.3.22"
+
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
+
checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
dependencies = [
 "itoa",
 "serde",
@@ -2905,9 +2926,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"

[[package]]
name = "time-macros"
-
version = "0.2.9"
+
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
+
checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
dependencies = [
 "time-core",
]
@@ -2969,7 +2990,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]

[[package]]
@@ -3054,7 +3075,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]

[[package]]
@@ -3084,7 +3105,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08aacc136419ba433b3f9bfd434a1bb62fe385328935e6ac11d952122b8a8cb"
dependencies = [
-
 "time 0.3.22",
+
 "time 0.3.23",
 "tracing",
 "tracing-core",
 "tracing-subscriber",
@@ -3319,7 +3340,7 @@ dependencies = [
 "once_cell",
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
 "wasm-bindgen-shared",
]

@@ -3341,7 +3362,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
 "wasm-bindgen-backend",
 "wasm-bindgen-shared",
]
@@ -3490,5 +3511,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
 "proc-macro2",
 "quote",
-
 "syn 2.0.23",
+
 "syn 2.0.25",
]
modified radicle-httpd/Cargo.toml
@@ -24,6 +24,7 @@ fastrand = { version = "1.9.0" }
flate2 = { version = "1" }
hyper = { version = "0.14.17", default-features = false }
lexopt = { version = "0.2.1" }
+
lru = { version = "0.10.0" }
nonempty = { version = "0.8.1", features = ["serialize"] }
radicle-surf = { version = "0.14.0", default-features = false, features = ["serde"] }
serde = { version = "1", features = ["derive"] }
modified radicle-httpd/src/api.rs
@@ -25,6 +25,9 @@ mod error;
mod json;
mod v1;

+
use crate::cache::Cache;
+
use crate::Options;
+

pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// Identifier for sessions
@@ -34,13 +37,15 @@ type SessionId = String;
pub struct Context {
    profile: Arc<Profile>,
    sessions: Arc<RwLock<HashMap<SessionId, auth::Session>>>,
+
    cache: Option<Cache>,
}

impl Context {
-
    pub fn new(profile: Arc<Profile>) -> Self {
+
    pub fn new(profile: Arc<Profile>, options: &Options) -> Self {
        Self {
            profile,
            sessions: Default::default(),
+
            cache: options.cache.map(Cache::new),
        }
    }

modified radicle-httpd/src/api/v1/projects.rs
@@ -309,12 +309,24 @@ async fn tree_handler(
    State(ctx): State<Context>,
    Path((project, sha, path)): Path<(Id, Oid, String)>,
) -> impl IntoResponse {
+
    if let Some(ref cache) = ctx.cache {
+
        let cache = &mut cache.tree.lock().await;
+
        if let Some(response) = cache.get(&(project, sha, path.clone())) {
+
            return Ok::<_, Error>(Json(response.clone()));
+
        }
+
    }
+

    let storage = &ctx.profile.storage;
    let repo = Repository::open(paths::repository(storage, &project))?;
    let tree = repo.tree(sha, &path)?;
    let stats = repo.stats_from(&sha)?;
    let response = api::json::tree(&tree, &path, &stats);

+
    if let Some(cache) = ctx.cache {
+
        let cache = &mut cache.tree.lock().await;
+
        cache.put((project, sha, path.clone()), response.clone());
+
    }
+

    Ok::<_, Error>(Json(response))
}

added radicle-httpd/src/cache.rs
@@ -0,0 +1,22 @@
+
use std::num::NonZeroUsize;
+
use std::sync::Arc;
+

+
use lru::LruCache;
+
use tokio::sync::Mutex;
+

+
use radicle::prelude::Id;
+
use radicle_surf::Oid;
+

+
#[derive(Clone)]
+
pub struct Cache {
+
    pub tree: Arc<Mutex<LruCache<(Id, Oid, String), serde_json::Value>>>,
+
}
+

+
impl Cache {
+
    /// Creates a new cache of the given size.
+
    pub fn new(size: NonZeroUsize) -> Self {
+
        Cache {
+
            tree: Arc::new(Mutex::new(LruCache::new(size))),
+
        }
+
    }
+
}
modified radicle-httpd/src/lib.rs
@@ -4,6 +4,7 @@ pub mod error;

use std::collections::HashMap;
use std::net::SocketAddr;
+
use std::num::NonZeroUsize;
use std::process::Command;
use std::str;
use std::sync::Arc;
@@ -24,16 +25,21 @@ use tracing_extra::{tracing_middleware, ColoredStatus, Paint, RequestId, Tracing

mod api;
mod axum_extra;
+
mod cache;
mod git;
mod raw;
#[cfg(test)]
mod test;
mod tracing_extra;

+
/// Default cache HTTP size.
+
pub const DEFAULT_CACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(100) };
+

#[derive(Debug, Clone)]
pub struct Options {
    pub aliases: HashMap<String, Id>,
    pub listen: SocketAddr,
+
    pub cache: Option<NonZeroUsize>,
}

/// Run the Server.
@@ -101,7 +107,7 @@ pub async fn run(options: Options) -> anyhow::Result<()> {
/// Create a router consisting of other sub-routers.
fn router(options: Options, profile: Profile) -> anyhow::Result<Router> {
    let profile = Arc::new(profile);
-
    let ctx = api::Context::new(profile.clone());
+
    let ctx = api::Context::new(profile.clone(), &options);

    let api_router = api::router(ctx);
    let git_router = git::router(profile.clone(), options.aliases);
@@ -132,6 +138,7 @@ mod routes {
            super::Options {
                aliases: HashMap::new(),
                listen: SocketAddr::from(([0, 0, 0, 0], 8080)),
+
                cache: None,
            },
            test::profile(tmp.path(), [0xff; 32]),
        )
modified radicle-httpd/src/main.rs
@@ -1,3 +1,4 @@
+
use std::num::NonZeroUsize;
use std::{collections::HashMap, process};

use radicle::prelude::Id;
@@ -51,6 +52,7 @@ fn parse_options() -> Result<httpd::Options, lexopt::Error> {
    let mut parser = lexopt::Parser::from_env();
    let mut listen = None;
    let mut aliases = HashMap::new();
+
    let mut cache = Some(httpd::DEFAULT_CACHE_SIZE);

    while let Some(arg) = parser.next()? {
        match arg {
@@ -64,8 +66,12 @@ fn parse_options() -> Result<httpd::Options, lexopt::Error> {

                aliases.insert(alias, id);
            }
+
            Long("cache") => {
+
                let size = parser.value()?.parse()?;
+
                cache = NonZeroUsize::new(size);
+
            }
            Long("help") | Short('h') => {
-
                println!("usage: radicle-httpd [--listen <addr>] [--alias <name> <rid>]..");
+
                println!("usage: radicle-httpd [--listen <addr>] [--alias <name> <rid>] [--cache <size>]..");
                process::exit(0);
            }
            _ => return Err(arg.unexpected()),
@@ -74,5 +80,6 @@ fn parse_options() -> Result<httpd::Options, lexopt::Error> {
    Ok(httpd::Options {
        aliases,
        listen: listen.unwrap_or_else(|| ([0, 0, 0, 0], 8080).into()),
+
        cache,
    })
}
modified radicle-httpd/src/test.rs
@@ -203,7 +203,13 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G
        )
        .unwrap();

-
    Context::new(Arc::new(profile))
+
    let options = crate::Options {
+
        aliases: std::collections::HashMap::new(),
+
        listen: std::net::SocketAddr::from(([0, 0, 0, 0], 8080)),
+
        cache: Some(crate::DEFAULT_CACHE_SIZE),
+
    };
+

+
    Context::new(Arc::new(profile), &options)
}

/// Adds an authorized session to the Context::sessions HashMap.