Add caching with LRU cache under mutex
Caches responses of each GET handler in a separate capacity-limited cache (as a custom clone-able `CachedResponse` struct). Subsequent requests will build a `Response` from the cached bytes instead of re-querying the database and re-serializing the JSON. This greatly speeds up the list endpoints and `get_interior_ref_list`. Also caches the api-key-to-id mapping for `Owner`s in order to speed up frequent authentications. Each create handler clears the entire list response cache. Each delete handler also clears the entire list response cache and deletes the cached response for that key. Deleting an owner also deletes their entry in the `owner_ids_by_api_key` cache.
This commit is contained in:
Generated
+96
-45
@@ -5,6 +5,14 @@ name = "adler"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.13"
|
||||
@@ -103,7 +111,7 @@ version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -274,13 +282,31 @@ dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -382,7 +408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz_oxide 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -532,7 +558,7 @@ version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -551,7 +577,16 @@ dependencies = [
|
||||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -598,7 +633,7 @@ name = "hermit-abi"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -678,7 +713,7 @@ dependencies = [
|
||||
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -719,7 +754,7 @@ name = "iovec"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -751,7 +786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.73"
|
||||
version = "0.2.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -759,7 +794,7 @@ name = "listenfd"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -788,6 +823,14 @@ dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
@@ -882,7 +925,7 @@ dependencies = [
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -907,7 +950,7 @@ version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -954,7 +997,7 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.10.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -971,7 +1014,7 @@ version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -998,7 +1041,7 @@ version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1025,7 +1068,7 @@ dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1041,7 +1084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1069,7 +1112,7 @@ dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cloudabi 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"instant 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1257,7 +1300,7 @@ version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1275,7 +1318,7 @@ version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1349,7 +1392,7 @@ name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1361,7 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1516,7 +1559,7 @@ dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1526,7 +1569,7 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1617,21 +1660,24 @@ dependencies = [
|
||||
"anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async-trait 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"barrel 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 3.0.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http-api-problem 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipnetwork 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"listenfd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"refinery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sqlx 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-subscriber 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-subscriber 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"warp 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1643,7 +1689,7 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1672,7 +1718,7 @@ version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1715,7 +1761,7 @@ dependencies = [
|
||||
"hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipnetwork 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1799,7 +1845,7 @@ version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1853,7 +1899,7 @@ name = "time"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1872,7 +1918,7 @@ dependencies = [
|
||||
"futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio-named-pipes 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1956,13 +2002,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.17"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-attributes 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1977,7 +2023,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.11"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1989,7 +2035,7 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1999,7 +2045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2008,12 +2054,12 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -2025,7 +2071,7 @@ dependencies = [
|
||||
"serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sharded-slab 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-log 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -2212,7 +2258,7 @@ dependencies = [
|
||||
"tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"urlencoding 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -2270,6 +2316,7 @@ dependencies = [
|
||||
|
||||
[metadata]
|
||||
"checksum adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
"checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3"
|
||||
"checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
|
||||
"checksum alloc-no-stdlib 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5192ec435945d87bc2f70992b4d818154b5feede43c09fb7592146374eac90a6"
|
||||
"checksum alloc-stdlib 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2"
|
||||
@@ -2304,6 +2351,8 @@ dependencies = [
|
||||
"checksum clap_derive 3.0.0-beta.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fb51c9e75b94452505acd21d929323f5a5c6c4735a852adbd39ef5fb1b014f30"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum cloudabi 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
|
||||
"checksum const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a"
|
||||
"checksum const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a"
|
||||
"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
|
||||
"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
|
||||
"checksum cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
||||
@@ -2338,6 +2387,7 @@ dependencies = [
|
||||
"checksum generic-array 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "60fb4bb6bba52f78a471264d9a3b7d026cc0af47b22cd2cffbc0b787ca003e63"
|
||||
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
"checksum h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
|
||||
"checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead"
|
||||
"checksum hashbrown 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34f595585f103464d8d2f6e9864682d74c1601fed5e07d62b1c9058dba8246fb"
|
||||
"checksum headers 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f"
|
||||
"checksum headers-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
|
||||
@@ -2360,11 +2410,12 @@ dependencies = [
|
||||
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
|
||||
"checksum libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
||||
"checksum listenfd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "492158e732f2e2de81c592f0a2427e57e12cd3d59877378fe7af624b6bbe0ca1"
|
||||
"checksum lock_api 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
|
||||
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||
"checksum lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "35c456c123957de3a220cd03786e0d86aa542a88b46029973b542f426da6ef34"
|
||||
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
"checksum matchers 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
||||
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||
@@ -2489,13 +2540,13 @@ dependencies = [
|
||||
"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
|
||||
"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
||||
"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
|
||||
"checksum tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dbdf4ccd1652592b01286a5dbe1e2a77d78afaa34beadd9872a5f7396f92aaa9"
|
||||
"checksum tracing 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178"
|
||||
"checksum tracing-attributes 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f0693bf8d6f2bf22c690fc61a9d21ac69efdbb894a17ed596b9af0f01e64b84b"
|
||||
"checksum tracing-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f"
|
||||
"checksum tracing-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b2734b5a028fa697686f16c6d18c2c6a3c7e41513f9a213abb6754c4acb3c8d7"
|
||||
"checksum tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
|
||||
"checksum tracing-log 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9"
|
||||
"checksum tracing-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6ccba2f8f16e0ed268fc765d9b7ff22e965e7185d32f8f1ec8294fe17d86e79"
|
||||
"checksum tracing-subscriber 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e4f5dd7095c2481b7b3cbed71c8de53085fb3542bc3c2b4c73cba43e8f11c7ba"
|
||||
"checksum tracing-subscriber 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc"
|
||||
"checksum try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
"checksum tungstenite 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e"
|
||||
"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
|
||||
|
||||
+4
-1
@@ -13,7 +13,7 @@ dotenv = "0.15"
|
||||
http-api-problem = { version = "0.17", features = ["with-warp"] }
|
||||
hyper = "0.13"
|
||||
listenfd = "0.3"
|
||||
tokio = { version = "0.2", features = ["macros"] }
|
||||
tokio = { version = "0.2", features = ["macros", "rt-threaded", "sync"] }
|
||||
sqlx = { version = "0.3", default-features = false, features = [ "runtime-tokio", "macros", "postgres", "chrono", "uuid", "ipnetwork", "json" ] }
|
||||
warp = { version = "0.2", features = ["compression"] }
|
||||
refinery = { version = "0.3.0", features = [ "tokio-postgres", "tokio" ] }
|
||||
@@ -28,3 +28,6 @@ async-trait = "0.1"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.2"
|
||||
tracing-futures = "0.2"
|
||||
lru = "0.5"
|
||||
http = "0.2"
|
||||
bytes = "0.5"
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
use anyhow::Result;
|
||||
use lru::LruCache;
|
||||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::debug;
|
||||
use warp::{Rejection, Reply};
|
||||
|
||||
use super::CachedResponse;
|
||||
use crate::problem::{reject_anyhow, unpack_problem};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Cache<K, V>
|
||||
where
|
||||
K: Eq + Hash + Debug,
|
||||
V: Clone,
|
||||
{
|
||||
pub name: String,
|
||||
pub lru_mutex: Arc<Mutex<LruCache<K, V>>>,
|
||||
pub log_keys: bool,
|
||||
}
|
||||
|
||||
impl<K, V> Cache<K, V>
|
||||
where
|
||||
K: Eq + Hash + Debug,
|
||||
V: Clone,
|
||||
{
|
||||
pub fn new(name: &str, capacity: usize) -> Self {
|
||||
Cache {
|
||||
name: name.to_string(),
|
||||
lru_mutex: Arc::new(Mutex::new(LruCache::new(capacity))),
|
||||
log_keys: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log_keys(mut self, value: bool) -> Self {
|
||||
self.log_keys = value;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn log_with_key(&self, key: &K, message: &str) {
|
||||
if self.log_keys {
|
||||
debug!(cache = %self.name, key = ?key, message);
|
||||
} else {
|
||||
debug!(cache = %self.name, message);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get<G, F>(&self, key: K, getter: G) -> Result<V>
|
||||
where
|
||||
G: Fn() -> F,
|
||||
F: Future<Output = Result<V>>,
|
||||
{
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
if let Some(value) = guard.get(&key) {
|
||||
self.log_with_key(&key, "get: hit");
|
||||
return Ok(value.clone());
|
||||
}
|
||||
drop(guard);
|
||||
|
||||
self.log_with_key(&key, "get: miss");
|
||||
let value = getter().await?;
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
guard.put(key, value.clone());
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub async fn delete(&self, key: K) -> Result<Option<V>> {
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
let value = guard.pop(&key);
|
||||
self.log_with_key(&key, "delete");
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub async fn clear(&self) {
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
guard.clear();
|
||||
debug!(cache = %self.name, "cache clear");
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> Cache<K, CachedResponse>
|
||||
where
|
||||
K: Eq + Hash + Debug,
|
||||
{
|
||||
pub async fn get_response<G, F, R>(
|
||||
&self,
|
||||
key: K,
|
||||
getter: G,
|
||||
) -> Result<CachedResponse, Rejection>
|
||||
where
|
||||
G: Fn() -> F,
|
||||
F: Future<Output = Result<R>>,
|
||||
R: Reply,
|
||||
{
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
if let Some(value) = guard.get(&key) {
|
||||
self.log_with_key(&key, "get_response: hit");
|
||||
return Ok(value.clone());
|
||||
}
|
||||
drop(guard);
|
||||
|
||||
self.log_with_key(&key, "get_response: miss");
|
||||
let reply = getter().await.map_err(reject_anyhow);
|
||||
let cached_response = match reply {
|
||||
Ok(reply) => CachedResponse::from_reply(reply)
|
||||
.await
|
||||
.map_err(reject_anyhow)?,
|
||||
Err(rejection) => {
|
||||
let reply = unpack_problem(rejection).await?;
|
||||
CachedResponse::from_reply(reply)
|
||||
.await
|
||||
.map_err(reject_anyhow)?
|
||||
}
|
||||
};
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
guard.put(key, cached_response.clone());
|
||||
|
||||
Ok(cached_response)
|
||||
}
|
||||
|
||||
pub async fn delete_response(&self, key: K) -> Result<Option<CachedResponse>> {
|
||||
let mut guard = self.lru_mutex.lock().await;
|
||||
let cached_response = guard.pop(&key);
|
||||
self.log_with_key(&key, "delete_response");
|
||||
|
||||
Ok(cached_response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
use anyhow::Result;
|
||||
use http::{HeaderMap, HeaderValue, Response, StatusCode, Version};
|
||||
use hyper::body::{to_bytes, Body, Bytes};
|
||||
use warp::Reply;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CachedResponse {
|
||||
pub status: StatusCode,
|
||||
pub version: Version,
|
||||
pub headers: HeaderMap<HeaderValue>,
|
||||
pub body: Bytes,
|
||||
}
|
||||
|
||||
impl CachedResponse {
|
||||
pub async fn from_reply<T>(reply: T) -> Result<Self>
|
||||
where
|
||||
T: Reply,
|
||||
{
|
||||
let mut response = reply.into_response();
|
||||
Ok(CachedResponse {
|
||||
status: response.status(),
|
||||
version: response.version(),
|
||||
headers: response.headers().clone(),
|
||||
body: to_bytes(response.body_mut()).await?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Reply for CachedResponse {
|
||||
fn into_response(self) -> warp::reply::Response {
|
||||
match Response::builder()
|
||||
.status(self.status)
|
||||
.version(self.version)
|
||||
.body(Body::from(self.body))
|
||||
{
|
||||
Ok(mut response) => {
|
||||
let headers = response.headers_mut();
|
||||
for (header, value) in self.headers.iter() {
|
||||
headers.insert(header, value.clone());
|
||||
}
|
||||
response
|
||||
}
|
||||
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
use std::fmt::Debug;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::models::ListParams;
|
||||
|
||||
mod cache;
|
||||
mod cached_response;
|
||||
|
||||
pub use cache::Cache;
|
||||
pub use cached_response::CachedResponse;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Caches {
|
||||
pub owner_ids_by_api_key: Cache<Uuid, i32>,
|
||||
pub shop: Cache<i32, CachedResponse>,
|
||||
pub owner: Cache<i32, CachedResponse>,
|
||||
pub interior_ref_list: Cache<i32, CachedResponse>,
|
||||
pub list_shops: Cache<ListParams, CachedResponse>,
|
||||
pub list_owners: Cache<ListParams, CachedResponse>,
|
||||
pub list_interior_ref_lists: Cache<ListParams, CachedResponse>,
|
||||
}
|
||||
|
||||
impl Caches {
|
||||
pub fn initialize() -> Self {
|
||||
Caches {
|
||||
owner_ids_by_api_key: Cache::new("owner_ids_by_api_key", 100).log_keys(false),
|
||||
shop: Cache::new("shop", 100),
|
||||
owner: Cache::new("owner", 100),
|
||||
interior_ref_list: Cache::new("interior_ref_list", 100),
|
||||
list_shops: Cache::new("list_shops", 100),
|
||||
list_owners: Cache::new("list_owners", 100),
|
||||
list_interior_ref_lists: Cache::new("list_interior_ref_lists", 100),
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-6
@@ -45,7 +45,8 @@ pub fn get_shop(env: Environment) -> impl Filter<Extract = impl Reply, Error = R
|
||||
pub fn create_shop(
|
||||
env: Environment,
|
||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||
warp::post()
|
||||
warp::path::end()
|
||||
.and(warp::post())
|
||||
.and(json_body::<Shop>())
|
||||
.and(with_env(env))
|
||||
.and_then(handlers::create_shop)
|
||||
@@ -64,7 +65,8 @@ pub fn delete_shop(
|
||||
pub fn list_shops(
|
||||
env: Environment,
|
||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||
warp::get()
|
||||
warp::path::end()
|
||||
.and(warp::get())
|
||||
.and(warp::query::<ListParams>())
|
||||
.and(with_env(env))
|
||||
.and_then(handlers::list_shops)
|
||||
@@ -80,7 +82,8 @@ pub fn get_owner(env: Environment) -> impl Filter<Extract = impl Reply, Error =
|
||||
pub fn create_owner(
|
||||
env: Environment,
|
||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||
warp::post()
|
||||
warp::path::end()
|
||||
.and(warp::post())
|
||||
.and(json_body::<Owner>())
|
||||
.and(warp::addr::remote())
|
||||
.and(with_env(env))
|
||||
@@ -100,7 +103,8 @@ pub fn delete_owner(
|
||||
pub fn list_owners(
|
||||
env: Environment,
|
||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||
warp::get()
|
||||
warp::path::end()
|
||||
.and(warp::get())
|
||||
.and(warp::query::<ListParams>())
|
||||
.and(with_env(env))
|
||||
.and_then(handlers::list_owners)
|
||||
@@ -118,7 +122,8 @@ pub fn get_interior_ref_list(
|
||||
pub fn create_interior_ref_list(
|
||||
env: Environment,
|
||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||
warp::post()
|
||||
warp::path::end()
|
||||
.and(warp::post())
|
||||
.and(json_body::<InteriorRefList>())
|
||||
.and(with_env(env))
|
||||
.and_then(handlers::create_interior_ref_list)
|
||||
@@ -137,7 +142,8 @@ pub fn delete_interior_ref_list(
|
||||
pub fn list_interior_ref_lists(
|
||||
env: Environment,
|
||||
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
|
||||
warp::get()
|
||||
warp::path::end()
|
||||
.and(warp::get())
|
||||
.and(warp::query::<ListParams>())
|
||||
.and(with_env(env))
|
||||
.and_then(handlers::list_interior_ref_lists)
|
||||
|
||||
+82
-21
@@ -2,6 +2,7 @@ use anyhow::{anyhow, Result};
|
||||
use ipnetwork::IpNetwork;
|
||||
use sqlx::postgres::PgPool;
|
||||
use std::net::SocketAddr;
|
||||
use tracing::instrument;
|
||||
use uuid::Uuid;
|
||||
use warp::http::StatusCode;
|
||||
use warp::reply::{json, with_header, with_status};
|
||||
@@ -10,9 +11,17 @@ use warp::{Rejection, Reply};
|
||||
use super::models::{InteriorRefList, ListParams, Model, Owner, Shop};
|
||||
use super::problem::{forbidden_no_api_key, forbidden_no_owner, reject_anyhow};
|
||||
use super::Environment;
|
||||
use crate::caches::Cache;
|
||||
|
||||
pub async fn authenticate(api_key: Option<Uuid>, db: &PgPool) -> Result<i32> {
|
||||
#[instrument(level = "debug", skip(db, cache, api_key))]
|
||||
pub async fn authenticate(
|
||||
db: &PgPool,
|
||||
cache: &Cache<Uuid, i32>,
|
||||
api_key: Option<Uuid>,
|
||||
) -> Result<i32> {
|
||||
if let Some(api_key) = api_key {
|
||||
cache
|
||||
.get(api_key, || async {
|
||||
Ok(
|
||||
sqlx::query!("SELECT id FROM owners WHERE api_key = $1", api_key)
|
||||
.fetch_one(db)
|
||||
@@ -25,36 +34,50 @@ pub async fn authenticate(api_key: Option<Uuid>, db: &PgPool) -> Result<i32> {
|
||||
})?
|
||||
.id,
|
||||
)
|
||||
})
|
||||
.await
|
||||
} else {
|
||||
// TODO: this should be 401 status instead
|
||||
Err(forbidden_no_api_key())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_shop(id: i32, env: Environment) -> Result<impl Reply, Rejection> {
|
||||
let shop = Shop::get(&env.db, id).await.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.shop
|
||||
.get_response(id, || async {
|
||||
let shop = Shop::get(&env.db, id).await?;
|
||||
let reply = json(&shop);
|
||||
let reply = with_status(reply, StatusCode::OK);
|
||||
Ok(reply)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_shops(
|
||||
list_params: ListParams,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let shops = Shop::list(&env.db, list_params)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.list_shops
|
||||
.get_response(list_params.clone(), || async {
|
||||
let shops = Shop::list(&env.db, &list_params).await?;
|
||||
let reply = json(&shops);
|
||||
let reply = with_status(reply, StatusCode::OK);
|
||||
Ok(reply)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn create_shop(shop: Shop, env: Environment) -> Result<impl Reply, Rejection> {
|
||||
// TODO: authenticate
|
||||
// TODO: return 400 error with message if unique key is violated
|
||||
let saved_shop = shop.save(&env.db).await.map_err(reject_anyhow)?;
|
||||
let url = saved_shop.url(&env.api_url).map_err(reject_anyhow)?;
|
||||
let reply = json(&saved_shop);
|
||||
let reply = with_header(reply, "Location", url.as_str());
|
||||
let reply = with_status(reply, StatusCode::CREATED);
|
||||
env.caches.list_shops.clear().await;
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
@@ -63,33 +86,46 @@ pub async fn delete_shop(
|
||||
api_key: Option<Uuid>,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let owner_id = authenticate(api_key, &env.db)
|
||||
let owner_id = authenticate(&env.db, &env.caches.owner_ids_by_api_key, api_key)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
dbg!(owner_id);
|
||||
Shop::delete(&env.db, owner_id, id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.shop
|
||||
.delete_response(id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches.list_shops.clear().await;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
pub async fn get_owner(id: i32, env: Environment) -> Result<impl Reply, Rejection> {
|
||||
let owner = Owner::get(&env.db, id).await.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.owner
|
||||
.get_response(id, || async {
|
||||
let owner = Owner::get(&env.db, id).await?;
|
||||
let reply = json(&owner);
|
||||
let reply = with_status(reply, StatusCode::OK);
|
||||
Ok(reply)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_owners(
|
||||
list_params: ListParams,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let owners = Owner::list(&env.db, list_params)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.list_owners
|
||||
.get_response(list_params.clone(), || async {
|
||||
let owners = Owner::list(&env.db, &list_params).await?;
|
||||
let reply = json(&owners);
|
||||
let reply = with_status(reply, StatusCode::OK);
|
||||
Ok(reply)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn create_owner(
|
||||
@@ -97,6 +133,7 @@ pub async fn create_owner(
|
||||
remote_addr: Option<SocketAddr>,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
// TODO: authenticate and get api_key from header
|
||||
let owner_with_ip = match remote_addr {
|
||||
Some(addr) => Owner {
|
||||
ip_address: Some(IpNetwork::from(addr.ip())),
|
||||
@@ -109,6 +146,7 @@ pub async fn create_owner(
|
||||
let reply = json(&saved_owner);
|
||||
let reply = with_header(reply, "Location", url.as_str());
|
||||
let reply = with_status(reply, StatusCode::CREATED);
|
||||
env.caches.list_owners.clear().await;
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
@@ -117,41 +155,58 @@ pub async fn delete_owner(
|
||||
api_key: Option<Uuid>,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let owner_id = authenticate(api_key, &env.db)
|
||||
let owner_id = authenticate(&env.db, &env.caches.owner_ids_by_api_key, api_key)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
dbg!(owner_id);
|
||||
Owner::delete(&env.db, owner_id, id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.owner
|
||||
.delete_response(id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.owner_ids_by_api_key
|
||||
.delete(api_key.expect("api-key has been validated during authenticate"))
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches.list_owners.clear().await;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
pub async fn get_interior_ref_list(id: i32, env: Environment) -> Result<impl Reply, Rejection> {
|
||||
let interior_ref_list = InteriorRefList::get(&env.db, id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.interior_ref_list
|
||||
.get_response(id, || async {
|
||||
let interior_ref_list = InteriorRefList::get(&env.db, id).await?;
|
||||
let reply = json(&interior_ref_list);
|
||||
let reply = with_status(reply, StatusCode::OK);
|
||||
Ok(reply)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_interior_ref_lists(
|
||||
list_params: ListParams,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let interior_ref_lists = InteriorRefList::list(&env.db, list_params)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.list_interior_ref_lists
|
||||
.get_response(list_params.clone(), || async {
|
||||
let interior_ref_lists = InteriorRefList::list(&env.db, &list_params).await?;
|
||||
let reply = json(&interior_ref_lists);
|
||||
let reply = with_status(reply, StatusCode::OK);
|
||||
Ok(reply)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn create_interior_ref_list(
|
||||
interior_ref_list: InteriorRefList,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
// TODO: authenticate
|
||||
let saved_interior_ref_list = interior_ref_list
|
||||
.save(&env.db)
|
||||
.await
|
||||
@@ -162,6 +217,7 @@ pub async fn create_interior_ref_list(
|
||||
let reply = json(&saved_interior_ref_list);
|
||||
let reply = with_header(reply, "Location", url.as_str());
|
||||
let reply = with_status(reply, StatusCode::CREATED);
|
||||
env.caches.list_interior_ref_lists.clear().await;
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
@@ -170,12 +226,17 @@ pub async fn delete_interior_ref_list(
|
||||
api_key: Option<Uuid>,
|
||||
env: Environment,
|
||||
) -> Result<impl Reply, Rejection> {
|
||||
let owner_id = authenticate(api_key, &env.db)
|
||||
let owner_id = authenticate(&env.db, &env.caches.owner_ids_by_api_key, api_key)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
dbg!(owner_id);
|
||||
InteriorRefList::delete(&env.db, owner_id, id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches
|
||||
.interior_ref_list
|
||||
.delete_response(id)
|
||||
.await
|
||||
.map_err(reject_anyhow)?;
|
||||
env.caches.list_interior_ref_lists.clear().await;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
@@ -12,12 +12,15 @@ use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use url::Url;
|
||||
use warp::Filter;
|
||||
|
||||
mod caches;
|
||||
mod db;
|
||||
mod filters;
|
||||
mod handlers;
|
||||
mod models;
|
||||
mod problem;
|
||||
|
||||
use caches::Caches;
|
||||
|
||||
#[derive(Clap)]
|
||||
#[clap(version = "0.1.0", author = "Tyler Hallada <tyler@hallada.net>")]
|
||||
struct Opts {
|
||||
@@ -28,6 +31,7 @@ struct Opts {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Environment {
|
||||
pub db: PgPool,
|
||||
pub caches: Caches,
|
||||
pub api_url: Url,
|
||||
}
|
||||
|
||||
@@ -38,6 +42,7 @@ impl Environment {
|
||||
.max_size(5)
|
||||
.build(&env::var("DATABASE_URL")?)
|
||||
.await?,
|
||||
caches: Caches::initialize(),
|
||||
api_url,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -50,11 +50,10 @@ impl Model for InteriorRefList {
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self> {
|
||||
Ok(
|
||||
sqlx::query_as_unchecked!(Self, "SELECT * FROM interior_ref_lists WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await?,
|
||||
)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, db))]
|
||||
@@ -95,7 +94,7 @@ impl Model for InteriorRefList {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>> {
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>> {
|
||||
let result = if let Some(order_by) = list_params.get_order_by() {
|
||||
sqlx::query_as_unchecked!(
|
||||
Self,
|
||||
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
use serde::Deserialize;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub mod interior_ref_list;
|
||||
pub mod model;
|
||||
@@ -11,7 +12,7 @@ pub use model::Model;
|
||||
pub use owner::Owner;
|
||||
pub use shop::Shop;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||
pub enum Order {
|
||||
Asc,
|
||||
Desc,
|
||||
@@ -30,7 +31,7 @@ impl fmt::Display for Order {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||
pub struct ListParams {
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
|
||||
+1
-1
@@ -25,5 +25,5 @@ where
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self>;
|
||||
async fn save(self, db: &PgPool) -> Result<Self>;
|
||||
async fn delete(db: &PgPool, owner_id: i32, id: i32) -> Result<u64>;
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>>;
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>>;
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use ipnetwork::IpNetwork;
|
||||
@@ -34,11 +34,10 @@ impl Model for Owner {
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self> {
|
||||
Ok(
|
||||
sqlx::query_as!(Self, "SELECT * FROM owners WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await?,
|
||||
)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
@@ -73,7 +72,7 @@ impl Model for Owner {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>> {
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>> {
|
||||
let result = if let Some(order_by) = list_params.get_order_by() {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -35,11 +35,10 @@ impl Model for Shop {
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self> {
|
||||
Ok(
|
||||
sqlx::query_as!(Self, "SELECT * FROM shops WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await?,
|
||||
)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
@@ -78,7 +77,7 @@ impl Model for Shop {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>> {
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>> {
|
||||
let result = if let Some(order_by) = list_params.get_order_by() {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Test Shop",
|
||||
"owner_id": 2,
|
||||
"description": "for testing",
|
||||
"is_not_sell_buy": true,
|
||||
"sell_buy_list_id": 1,
|
||||
"vendor_id": 1,
|
||||
"vendor_gold": 0
|
||||
}
|
||||
Reference in New Issue
Block a user