perf: enable HTTP/2, remove redundant hyper dep, use async RwLock

- Enable HTTP/2 auto-detection in axum (add 'http2' feature)
- Remove direct hyper dependency with 'full' features (already transitive via axum/reqwest)
- Replace std::sync::RwLock with tokio::sync::RwLock in oidc_service.rs and file_system_i18n_service.rs to prevent async deadlocks
This commit is contained in:
Dionisio
2026-03-05 18:27:13 +01:00
parent 4d81bcbd7b
commit 56d73d1fc6
4 changed files with 14 additions and 28 deletions
Generated
+4 -5
View File
@@ -723,7 +723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -1724,7 +1724,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -1817,7 +1817,6 @@ dependencies = [
"http-body",
"http-body-util",
"http-range-header",
"hyper",
"image",
"infer",
"jsonwebtoken",
@@ -2408,7 +2407,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -2927,7 +2926,7 @@ dependencies = [
"getrandom 0.4.1",
"once_cell",
"rustix",
"windows-sys 0.52.0",
"windows-sys 0.61.2",
]
[[package]]
+1 -2
View File
@@ -7,7 +7,7 @@ default-run = "oxicloud"
[dependencies]
mimalloc = { version = "0.1.48", default-features = false }
axum = { version = "0.8.8", features = ["multipart", "http1", "tokio", "macros"] }
axum = { version = "0.8.8", features = ["multipart", "http1", "http2", "tokio", "macros"] }
tokio = { version = "1.49.0", features = ["rt-multi-thread", "macros", "io-util", "net", "time", "sync", "fs"] }
tokio-util = { version = "0.7.18", features = ["io", "codec", "compat"] }
tokio-stream = { version = "0.1.18", features = ["fs"] }
@@ -32,7 +32,6 @@ sqlx = { version = "0.8.6", features = ["postgres", "runtime-tokio", "tls-rustls
jsonwebtoken = { version = "10.3.0", features = ["rust_crypto"] }
argon2 = "0.5.3"
rand_core = { version = "0.6", features = ["std", "getrandom"] }
hyper = { version = "1.8.1", features = ["full"] }
quick-xml = "0.39.2"
dotenvy = "0.15.7"
moka = { version = "0.12", features = ["future", "sync"] }
@@ -1,7 +1,7 @@
use serde_json::Value;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::RwLock;
use tokio::sync::RwLock;
use tokio::fs;
use crate::domain::services::i18n_service::{I18nError, I18nResult, I18nService, Locale};
@@ -66,7 +66,7 @@ impl I18nService for FileSystemI18nService {
async fn translate(&self, key: &str, locale: Locale) -> I18nResult<String> {
// Check if translations are cached
{
let cache = self.cache.read().unwrap();
let cache = self.cache.read().await;
if let Some(translations) = cache.get(&locale) {
if let Some(value) = self.get_nested_value(translations, key) {
return Ok(value);
@@ -88,7 +88,7 @@ impl I18nService for FileSystemI18nService {
self.load_translations(locale).await?;
{
let cache = self.cache.read().unwrap();
let cache = self.cache.read().await;
if let Some(translations) = cache.get(&locale) {
if let Some(value) = self.get_nested_value(translations, key) {
return Ok(value);
@@ -131,7 +131,7 @@ impl I18nService for FileSystemI18nService {
// Update cache
{
let mut cache = self.cache.write().unwrap();
let mut cache = self.cache.write().await;
cache.insert(locale, translations);
}
+5 -17
View File
@@ -6,7 +6,7 @@
//! Compatible with Authentik, Keycloak, and any standard OIDC provider.
use serde::Deserialize;
use std::sync::RwLock;
use tokio::sync::RwLock;
use std::time::{Duration, Instant};
use crate::application::ports::auth_ports::{OidcIdClaims, OidcServicePort, OidcTokenSet};
@@ -144,10 +144,7 @@ impl OidcService {
async fn get_discovery(&self) -> Result<OidcDiscovery, DomainError> {
// Check cache first (return cached value only if not expired)
{
let cache = self
.discovery
.read()
.map_err(|_| DomainError::new(ErrorKind::InternalError, "OIDC", "Lock poisoned"))?;
let cache = self.discovery.read().await;
if let Some(ref cached) = *cache {
if !cached.is_expired() {
return Ok(cached.value.clone());
@@ -193,10 +190,7 @@ impl OidcService {
// Cache it with timestamp
{
let mut cache = self
.discovery
.write()
.map_err(|_| DomainError::new(ErrorKind::InternalError, "OIDC", "Lock poisoned"))?;
let mut cache = self.discovery.write().await;
*cache = Some(Cached::new(discovery.clone()));
}
@@ -207,10 +201,7 @@ impl OidcService {
async fn get_jwks(&self) -> Result<JwksDocument, DomainError> {
// Check cache first (return cached value only if not expired)
{
let cache = self
.jwks
.read()
.map_err(|_| DomainError::new(ErrorKind::InternalError, "OIDC", "Lock poisoned"))?;
let cache = self.jwks.read().await;
if let Some(ref cached) = *cache {
if !cached.is_expired() {
return Ok(cached.value.clone());
@@ -246,10 +237,7 @@ impl OidcService {
// Cache it with timestamp
{
let mut cache = self
.jwks
.write()
.map_err(|_| DomainError::new(ErrorKind::InternalError, "OIDC", "Lock poisoned"))?;
let mut cache = self.jwks.write().await;
*cache = Some(Cached::new(jwks.clone()));
}