httpd: Add a cache for `/tree`

This improves response time of:

- GET /api/v1/projects/<RID>/tree/<OID>/ from 205.71ms down to 376.4µs
- GET /api/v1/projects/<RID>/tree/<OID>/.nix from 111.06ms down to 351.70µs

Signed-off-by: xphoniex <dj.2dixx@gmail.com>
This commit is contained in:
xphoniex 2023-07-12 17:43:11 +00:00 committed by Alexis Sellier
parent b1f174817c
commit 8a61aece01
No known key found for this signature in database
8 changed files with 169 additions and 88 deletions

189
Cargo.lock generated
View File

@ -49,6 +49,17 @@ dependencies = [
"version_check", "version_check",
] ]
[[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]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.0.2" version = "1.0.2"
@ -177,13 +188,13 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.69" version = "0.1.71"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -499,9 +510,9 @@ dependencies = [
[[package]] [[package]]
name = "const-oid" name = "const-oid"
version = "0.9.3" version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6340df57935414636969091153f35f68d9f00bbc8fb4a9c6054706c213e6c6bc" checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747"
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
@ -511,9 +522,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.8" version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -575,16 +586,6 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df" 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]] [[package]]
name = "ctr" name = "ctr"
version = "0.9.2" version = "0.9.2"
@ -802,9 +803,9 @@ dependencies = [
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
@ -1053,7 +1054,16 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [ 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]] [[package]]
@ -1098,9 +1108,9 @@ dependencies = [
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.3.1" version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]] [[package]]
name = "hmac" name = "hmac"
@ -1269,7 +1279,7 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [ dependencies = [
"hermit-abi 0.3.1", "hermit-abi 0.3.2",
"libc", "libc",
"windows-sys", "windows-sys",
] ]
@ -1288,12 +1298,12 @@ dependencies = [
[[package]] [[package]]
name = "is-terminal" name = "is-terminal"
version = "0.4.8" version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [ dependencies = [
"hermit-abi 0.3.1", "hermit-abi 0.3.2",
"rustix 0.38.2", "rustix 0.38.4",
"windows-sys", "windows-sys",
] ]
@ -1457,13 +1467,22 @@ version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 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]] [[package]]
name = "matchers" name = "matchers"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [ dependencies = [
"regex-automata", "regex-automata 0.1.10",
] ]
[[package]] [[package]]
@ -1634,7 +1653,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [ dependencies = [
"hermit-abi 0.3.1", "hermit-abi 0.3.2",
"libc", "libc",
] ]
@ -1665,15 +1684,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 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]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -1761,7 +1771,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -1832,13 +1842,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "pretty_assertions" name = "pretty_assertions"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [ dependencies = [
"ctor",
"diff", "diff",
"output_vt100",
"yansi", "yansi",
] ]
@ -1868,9 +1876,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.63" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -2067,6 +2075,7 @@ dependencies = [
"flate2", "flate2",
"hyper", "hyper",
"lexopt", "lexopt",
"lru",
"nonempty 0.8.1", "nonempty 0.8.1",
"pretty_assertions", "pretty_assertions",
"radicle", "radicle",
@ -2078,7 +2087,7 @@ dependencies = [
"serde_json", "serde_json",
"tempfile", "tempfile",
"thiserror", "thiserror",
"time 0.3.22", "time 0.3.23",
"tokio", "tokio",
"tower", "tower",
"tower-http", "tower-http",
@ -2309,13 +2318,14 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.8.4" version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax 0.7.2", "regex-automata 0.3.2",
"regex-syntax 0.7.4",
] ]
[[package]] [[package]]
@ -2327,6 +2337,17 @@ dependencies = [
"regex-syntax 0.6.29", "regex-syntax 0.6.29",
] ]
[[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]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.29" version = "0.6.29"
@ -2335,9 +2356,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.7.2" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
[[package]] [[package]]
name = "rfc6979" name = "rfc6979"
@ -2379,9 +2400,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.22" version = "0.37.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"errno", "errno",
@ -2393,9 +2414,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.2" version = "0.38.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4" checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
dependencies = [ dependencies = [
"bitflags 2.3.3", "bitflags 2.3.3",
"errno", "errno",
@ -2453,29 +2474,29 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.166" version = "1.0.171"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.166" version = "1.0.171"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.99" version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed"
dependencies = [ dependencies = [
"indexmap 2.0.0", "indexmap 2.0.0",
"itoa", "itoa",
@ -2485,9 +2506,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_path_to_error" name = "serde_path_to_error"
version = "0.1.12" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b1b6471d7496b051e03f1958802a73f88b947866f5146f329e47e36554f4e55" checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a"
dependencies = [ dependencies = [
"itoa", "itoa",
"serde", "serde",
@ -2610,9 +2631,9 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.10.0" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]] [[package]]
name = "smawk" name = "smawk"
@ -2769,9 +2790,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.23" version = "2.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2805,7 +2826,7 @@ dependencies = [
"cfg-if", "cfg-if",
"fastrand", "fastrand",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"rustix 0.37.22", "rustix 0.37.23",
"windows-sys", "windows-sys",
] ]
@ -2846,22 +2867,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.40" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.40" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -2887,9 +2908,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.22" version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
dependencies = [ dependencies = [
"itoa", "itoa",
"serde", "serde",
@ -2905,9 +2926,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.9" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
dependencies = [ dependencies = [
"time-core", "time-core",
] ]
@ -2969,7 +2990,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -3054,7 +3075,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -3084,7 +3105,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08aacc136419ba433b3f9bfd434a1bb62fe385328935e6ac11d952122b8a8cb" checksum = "c08aacc136419ba433b3f9bfd434a1bb62fe385328935e6ac11d952122b8a8cb"
dependencies = [ dependencies = [
"time 0.3.22", "time 0.3.23",
"tracing", "tracing",
"tracing-core", "tracing-core",
"tracing-subscriber", "tracing-subscriber",
@ -3319,7 +3340,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3341,7 +3362,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3490,5 +3511,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.23", "syn 2.0.25",
] ]

View File

@ -24,6 +24,7 @@ fastrand = { version = "1.9.0" }
flate2 = { version = "1" } flate2 = { version = "1" }
hyper = { version = "0.14.17", default-features = false } hyper = { version = "0.14.17", default-features = false }
lexopt = { version = "0.2.1" } lexopt = { version = "0.2.1" }
lru = { version = "0.10.0" }
nonempty = { version = "0.8.1", features = ["serialize"] } nonempty = { version = "0.8.1", features = ["serialize"] }
radicle-surf = { version = "0.14.0", default-features = false, features = ["serde"] } radicle-surf = { version = "0.14.0", default-features = false, features = ["serde"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }

View File

@ -25,6 +25,9 @@ mod error;
mod json; mod json;
mod v1; mod v1;
use crate::cache::Cache;
use crate::Options;
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");
/// Identifier for sessions /// Identifier for sessions
@ -34,13 +37,15 @@ type SessionId = String;
pub struct Context { pub struct Context {
profile: Arc<Profile>, profile: Arc<Profile>,
sessions: Arc<RwLock<HashMap<SessionId, auth::Session>>>, sessions: Arc<RwLock<HashMap<SessionId, auth::Session>>>,
cache: Option<Cache>,
} }
impl Context { impl Context {
pub fn new(profile: Arc<Profile>) -> Self { pub fn new(profile: Arc<Profile>, options: &Options) -> Self {
Self { Self {
profile, profile,
sessions: Default::default(), sessions: Default::default(),
cache: options.cache.map(Cache::new),
} }
} }

View File

@ -309,12 +309,24 @@ async fn tree_handler(
State(ctx): State<Context>, State(ctx): State<Context>,
Path((project, sha, path)): Path<(Id, Oid, String)>, Path((project, sha, path)): Path<(Id, Oid, String)>,
) -> impl IntoResponse { ) -> 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 storage = &ctx.profile.storage;
let repo = Repository::open(paths::repository(storage, &project))?; let repo = Repository::open(paths::repository(storage, &project))?;
let tree = repo.tree(sha, &path)?; let tree = repo.tree(sha, &path)?;
let stats = repo.stats_from(&sha)?; let stats = repo.stats_from(&sha)?;
let response = api::json::tree(&tree, &path, &stats); 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)) Ok::<_, Error>(Json(response))
} }

View File

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

View File

@ -4,6 +4,7 @@ pub mod error;
use std::collections::HashMap; use std::collections::HashMap;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::num::NonZeroUsize;
use std::process::Command; use std::process::Command;
use std::str; use std::str;
use std::sync::Arc; use std::sync::Arc;
@ -24,16 +25,21 @@ use tracing_extra::{tracing_middleware, ColoredStatus, Paint, RequestId, Tracing
mod api; mod api;
mod axum_extra; mod axum_extra;
mod cache;
mod git; mod git;
mod raw; mod raw;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
mod tracing_extra; mod tracing_extra;
/// Default cache HTTP size.
pub const DEFAULT_CACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(100) };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Options { pub struct Options {
pub aliases: HashMap<String, Id>, pub aliases: HashMap<String, Id>,
pub listen: SocketAddr, pub listen: SocketAddr,
pub cache: Option<NonZeroUsize>,
} }
/// Run the Server. /// Run the Server.
@ -101,7 +107,7 @@ pub async fn run(options: Options) -> anyhow::Result<()> {
/// Create a router consisting of other sub-routers. /// Create a router consisting of other sub-routers.
fn router(options: Options, profile: Profile) -> anyhow::Result<Router> { fn router(options: Options, profile: Profile) -> anyhow::Result<Router> {
let profile = Arc::new(profile); 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 api_router = api::router(ctx);
let git_router = git::router(profile.clone(), options.aliases); let git_router = git::router(profile.clone(), options.aliases);
@ -132,6 +138,7 @@ mod routes {
super::Options { super::Options {
aliases: HashMap::new(), aliases: HashMap::new(),
listen: SocketAddr::from(([0, 0, 0, 0], 8080)), listen: SocketAddr::from(([0, 0, 0, 0], 8080)),
cache: None,
}, },
test::profile(tmp.path(), [0xff; 32]), test::profile(tmp.path(), [0xff; 32]),
) )

View File

@ -1,3 +1,4 @@
use std::num::NonZeroUsize;
use std::{collections::HashMap, process}; use std::{collections::HashMap, process};
use radicle::prelude::Id; 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 parser = lexopt::Parser::from_env();
let mut listen = None; let mut listen = None;
let mut aliases = HashMap::new(); let mut aliases = HashMap::new();
let mut cache = Some(httpd::DEFAULT_CACHE_SIZE);
while let Some(arg) = parser.next()? { while let Some(arg) = parser.next()? {
match arg { match arg {
@ -64,8 +66,12 @@ fn parse_options() -> Result<httpd::Options, lexopt::Error> {
aliases.insert(alias, id); aliases.insert(alias, id);
} }
Long("cache") => {
let size = parser.value()?.parse()?;
cache = NonZeroUsize::new(size);
}
Long("help") | Short('h') => { 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); process::exit(0);
} }
_ => return Err(arg.unexpected()), _ => return Err(arg.unexpected()),
@ -74,5 +80,6 @@ fn parse_options() -> Result<httpd::Options, lexopt::Error> {
Ok(httpd::Options { Ok(httpd::Options {
aliases, aliases,
listen: listen.unwrap_or_else(|| ([0, 0, 0, 0], 8080).into()), listen: listen.unwrap_or_else(|| ([0, 0, 0, 0], 8080).into()),
cache,
}) })
} }

View File

@ -203,7 +203,13 @@ fn seed_with_signer<G: Signer>(dir: &Path, profile: radicle::Profile, signer: &G
) )
.unwrap(); .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. /// Adds an authorized session to the Context::sessions HashMap.