don't spawn a new runtime every request

This commit is contained in:
Evan Almloff committed 2023-07-28 13:14:26 -07:00
1 parent cfd62e274e
commit fcb993a2cb
2 files changed
+29 -22

No files matched your search

+2 -1
View File
@@ -41,6 +41,7 @@ log = { workspace = true }
once_cell = "1.17.1" once_cell = "1.17.1"
thiserror = { workspace = true } thiserror = { workspace = true }
tokio = { workspace = true, features = ["full"], optional = true } tokio = { workspace = true, features = ["full"], optional = true }
tokio-util = { version = "0.7.8", features = ["rt"], optional = true }
object-pool = "0.5.4" object-pool = "0.5.4"
anymap = "0.12.1" anymap = "0.12.1"
@@ -68,7 +69,7 @@ hot-reload = ["serde_json", "futures-util"]
warp = ["dep:warp", "ssr"] warp = ["dep:warp", "ssr"]
axum = ["dep:axum", "tower-http", "ssr"] axum = ["dep:axum", "tower-http", "ssr"]
salvo = ["dep:salvo", "ssr"] salvo = ["dep:salvo", "ssr"]
ssr = ["server_fn/ssr", "tokio", "dioxus-ssr", "tower", "hyper", "http", "http-body", "dioxus-router/ssr", "tokio-stream"] ssr = ["server_fn/ssr", "tokio", "tokio-util", "dioxus-ssr", "tower", "hyper", "http", "http-body", "dioxus-router/ssr", "tokio-stream"]
default-tls = ["server_fn/default-tls"] default-tls = ["server_fn/default-tls"]
rustls = ["server_fn/rustls"] rustls = ["server_fn/rustls"]
+27 -21
View File
@@ -17,12 +17,9 @@ pub mod salvo_adapter;
#[cfg(feature = "warp")] #[cfg(feature = "warp")]
pub mod warp_adapter; pub mod warp_adapter;
use std::sync::{Arc, RwLock};
use http::StatusCode; use http::StatusCode;
use server_fn::{Encoding, Payload}; use server_fn::{Encoding, Payload};
use tokio::task::spawn_blocking; use std::sync::{Arc, RwLock};
use crate::{ use crate::{
layer::{BoxedService, Service}, layer::{BoxedService, Service},
@@ -93,27 +90,22 @@ impl Service for ServerFnHandler {
// Because the future returned by `server_fn_handler` is `Send`, and the future returned by this function must be send, we need to spawn a new runtime // Because the future returned by `server_fn_handler` is `Send`, and the future returned by this function must be send, we need to spawn a new runtime
let (resp_tx, resp_rx) = tokio::sync::oneshot::channel(); let (resp_tx, resp_rx) = tokio::sync::oneshot::channel();
spawn_blocking({ let pool = get_local_pool();
pool.spawn_pinned({
let function = function.clone(); let function = function.clone();
let mut server_context = server_context.clone(); let mut server_context = server_context.clone();
server_context.parts = parts; server_context.parts = parts;
move || { move || async move {
tokio::runtime::Runtime::new() let data = match function.encoding() {
.expect("couldn't spawn runtime") Encoding::Url | Encoding::Cbor => &body,
.block_on(async move { Encoding::GetJSON | Encoding::GetCBOR => &query,
let data = match function.encoding() { };
Encoding::Url | Encoding::Cbor => &body, let server_function_future = function.call((), data);
Encoding::GetJSON | Encoding::GetCBOR => &query, let server_function_future =
}; ProvideServerContext::new(server_function_future, server_context.clone());
let server_function_future = function.call((), data); let resp = server_function_future.await;
let server_function_future = ProvideServerContext::new(
server_function_future,
server_context.clone(),
);
let resp = server_function_future.await;
resp_tx.send(resp).unwrap(); resp_tx.send(resp).unwrap();
})
} }
}); });
let result = resp_rx.await.unwrap(); let result = resp_rx.await.unwrap();
@@ -158,3 +150,17 @@ impl Service for ServerFnHandler {
}) })
} }
} }
fn get_local_pool() -> tokio_util::task::LocalPoolHandle {
use once_cell::sync::OnceCell;
static LOCAL_POOL: OnceCell<tokio_util::task::LocalPoolHandle> = OnceCell::new();
LOCAL_POOL
.get_or_init(|| {
tokio_util::task::LocalPoolHandle::new(
std::thread::available_parallelism()
.map(Into::into)
.unwrap_or(1),
)
})
.clone()
}