1use std::ffi::OsString;2use std::sync::{Arc, OnceLock};34use r2d2::Pool;56use crate::session::NixSessionInner;7use crate::{Error, NixSession, Result};89pub struct NixSessionPool(Pool<NixSessionPoolInner>);10impl NixSessionPool {11 pub async fn new(flake: OsString, nix_args: Vec<OsString>) -> Result<Self> {12 let inner = tokio::task::block_in_place(|| {13 r2d2::Builder::<NixSessionPoolInner>::new()14 .min_idle(Some(0))15 .build(NixSessionPoolInner { flake, nix_args })16 })?;17 Ok(Self(inner))18 }19 pub async fn get(&self) -> Result<NixSession> {20 let v = tokio::task::block_in_place(|| self.0.get())?;21 Ok(NixSession(Arc::new(tokio::sync::Mutex::new(v))))22 }23}2425pub(crate) struct NixSessionPoolInner {26 flake: OsString,27 nix_args: Vec<OsString>,28}2930impl r2d2::ManageConnection for NixSessionPoolInner {31 type Connection = NixSessionInner;32 type Error = Error;33 fn connect(&self) -> std::result::Result<Self::Connection, Self::Error> {34 let _v = TOKIO_RUNTIME35 .get()36 .expect("missed tokio runtime init!")37 .enter();38 Ok(futures::executor::block_on(NixSessionInner::new(39 self.flake.as_os_str(),40 self.nix_args.iter().map(OsString::as_os_str),41 ))?)42 }4344 fn is_valid(&self, conn: &mut Self::Connection) -> std::result::Result<(), Self::Error> {45 let _v = TOKIO_RUNTIME46 .get()47 .expect("missed tokio runtime init!")48 .enter();49 let res = futures::executor::block_on(conn.execute_expression_number("2 + 2"))?;50 if res != 4 {51 52 return Err(Error::SessionInit("misbehaving session"));53 };54 Ok(())55 }5657 fn has_broken(&self, _conn: &mut Self::Connection) -> bool {58 false59 }60}61pub static TOKIO_RUNTIME: OnceLock<tokio::runtime::Handle> = OnceLock::new();