From e75e3eeea0c9c9303fb07aada97b644fc22db18c Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Mon, 7 Oct 2024 14:57:12 -0400 Subject: [PATCH 1/5] update shell.nix to python 3.12 --- shell.nix | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shell.nix b/shell.nix index 9c6ddb4..d61f0ed 100644 --- a/shell.nix +++ b/shell.nix @@ -2,11 +2,11 @@ (pkgs.buildFHSUserEnv { name = "pipzone"; targetPkgs = pkgs: (with pkgs; [ - python39 - python39Packages.pip - python39Packages.virtualenv - python39Packages.pytest - python39Packages.pyperf + python312 + python312Packages.pip + python312Packages.virtualenv + python312Packages.pytest + python312Packages.pyperf maturin ]); runScript = "bash"; From 1ffad821ef98468d930b1bcfb8a98c5436310f0f Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Mon, 7 Oct 2024 15:10:46 -0400 Subject: [PATCH 2/5] fix rt dropping before hrana close can be sent --- src/lib.rs | 72 ++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 03491cf..b54becf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,11 +3,25 @@ use pyo3::create_exception; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::{PyList, PyTuple}; -use std::cell::RefCell; +use std::cell::{OnceCell, RefCell}; use std::sync::Arc; +use tokio::runtime::{Handle, Runtime}; const LEGACY_TRANSACTION_CONTROL: i32 = -1; +fn rt() -> Handle { + const RT: OnceCell = OnceCell::new(); + + RT.get_or_init(|| { + tokio::runtime::Builder::new_multi_thread() + .worker_threads(1) + .build() + .unwrap() + }) + .handle() + .clone() +} + fn to_py_err(error: libsql_core::errors::Error) -> PyErr { let msg = match error { libsql::Error::SqliteFailure(_, err) => err, @@ -99,7 +113,7 @@ fn _connect_core( ) -> PyResult { let ver = env!("CARGO_PKG_VERSION"); let ver = format!("libsql-python-rpc-{ver}"); - let rt = tokio::runtime::Runtime::new().unwrap(); + let rt = rt(); let encryption_config = match encryption_key { Some(key) => { let cipher = libsql::Cipher::default(); @@ -147,9 +161,8 @@ fn _connect_core( db, conn: Arc::new(ConnectionGuard { conn: Some(conn), - handle: rt.handle().clone(), + handle: rt.clone(), }), - rt, isolation_level, autocommit, }) @@ -186,7 +199,6 @@ impl Drop for ConnectionGuard { pub struct Connection { db: libsql_core::Database, conn: Arc, - rt: tokio::runtime::Runtime, isolation_level: Option, autocommit: i32, } @@ -199,7 +211,6 @@ impl Connection { fn cursor(&self) -> PyResult { Ok(Cursor { arraysize: 1, - rt: self.rt.handle().clone(), conn: self.conn.clone(), stmt: RefCell::new(None), rows: RefCell::new(None), @@ -212,24 +223,19 @@ impl Connection { fn sync(self_: PyRef<'_, Self>, py: Python<'_>) -> PyResult<()> { let fut = { - let _enter = self_.rt.enter(); + let _enter = rt().enter(); self_.db.sync() }; tokio::pin!(fut); - self_ - .rt - .block_on(check_signals(py, fut)) - .map_err(to_py_err)?; + rt().block_on(check_signals(py, fut)).map_err(to_py_err)?; Ok(()) } fn commit(self_: PyRef<'_, Self>) -> PyResult<()> { // TODO: Switch to libSQL transaction API if !self_.conn.is_autocommit() { - self_ - .rt - .block_on(async { self_.conn.execute("COMMIT", ()).await }) + rt().block_on(async { self_.conn.execute("COMMIT", ()).await }) .map_err(to_py_err)?; } Ok(()) @@ -238,9 +244,7 @@ impl Connection { fn rollback(self_: PyRef<'_, Self>) -> PyResult<()> { // TODO: Switch to libSQL transaction API if !self_.conn.is_autocommit() { - self_ - .rt - .block_on(async { self_.conn.execute("ROLLBACK", ()).await }) + rt().block_on(async { self_.conn.execute("ROLLBACK", ()).await }) .map_err(to_py_err)?; } Ok(()) @@ -252,8 +256,7 @@ impl Connection { parameters: Option<&PyTuple>, ) -> PyResult { let cursor = Connection::cursor(&self_)?; - let rt = self_.rt.handle(); - rt.block_on(async { execute(&cursor, sql, parameters).await })?; + rt().block_on(async { execute(&cursor, sql, parameters).await })?; Ok(cursor) } @@ -265,17 +268,15 @@ impl Connection { let cursor = Connection::cursor(&self_)?; for parameters in parameters.unwrap().iter() { let parameters = parameters.extract::<&PyTuple>()?; - self_ - .rt - .block_on(async { execute(&cursor, sql.clone(), Some(parameters)).await })?; + rt().block_on(async { execute(&cursor, sql.clone(), Some(parameters)).await })?; } Ok(cursor) } fn executescript(self_: PyRef<'_, Self>, script: String) -> PyResult<()> { - let _ = self_.rt.block_on(async { - self_.conn.execute_batch(&script).await - }).map_err(to_py_err); + let _ = rt() + .block_on(async { self_.conn.execute_batch(&script).await }) + .map_err(to_py_err); Ok(()) } @@ -316,7 +317,6 @@ impl Connection { pub struct Cursor { #[pyo3(get, set)] arraysize: usize, - rt: tokio::runtime::Handle, conn: Arc, stmt: RefCell>, rows: RefCell>, @@ -336,9 +336,7 @@ impl Cursor { sql: String, parameters: Option<&PyTuple>, ) -> PyResult> { - self_ - .rt - .block_on(async { execute(&self_, sql, parameters).await })?; + rt().block_on(async { execute(&self_, sql, parameters).await })?; Ok(self_) } @@ -349,9 +347,7 @@ impl Cursor { ) -> PyResult> { for parameters in parameters.unwrap().iter() { let parameters = parameters.extract::<&PyTuple>()?; - self_ - .rt - .block_on(async { execute(&self_, sql.clone(), Some(parameters)).await })?; + rt().block_on(async { execute(&self_, sql.clone(), Some(parameters)).await })?; } Ok(self_) } @@ -360,9 +356,7 @@ impl Cursor { self_: PyRef<'a, Self>, script: String, ) -> PyResult> { - self_ - .rt - .block_on(async { self_.conn.execute_batch(&script).await }) + rt().block_on(async { self_.conn.execute_batch(&script).await }) .map_err(to_py_err)?; Ok(self_) } @@ -398,7 +392,7 @@ impl Cursor { let mut rows = self_.rows.borrow_mut(); match rows.as_mut() { Some(rows) => { - let row = self_.rt.block_on(rows.next()).map_err(to_py_err)?; + let row = rt().block_on(rows.next()).map_err(to_py_err)?; match row { Some(row) => { let row = convert_row(self_.py(), row, rows.column_count())?; @@ -422,8 +416,7 @@ impl Cursor { // done before iterating. if !*self_.done.borrow() { for _ in 0..size { - let row = self_ - .rt + let row = rt() .block_on(async { rows.next().await }) .map_err(to_py_err)?; match row { @@ -450,8 +443,7 @@ impl Cursor { Some(rows) => { let mut elements: Vec> = vec![]; loop { - let row = self_ - .rt + let row = rt() .block_on(async { rows.next().await }) .map_err(to_py_err)?; match row { From bde41ef592ef6f69f94392d96804f7bfa4fcc2cd Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Mon, 7 Oct 2024 15:11:52 -0400 Subject: [PATCH 3/5] release v0.0.40 --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66b3d4e..d91ee23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "libsql-python" -version = "0.0.40" +version = "0.0.41" dependencies = [ "libsql", "pyo3", diff --git a/Cargo.toml b/Cargo.toml index 4840dde..6a5ffe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libsql-python" -version = "0.0.40" +version = "0.0.41" edition = "2021" [lib] @@ -16,4 +16,4 @@ tracing-subscriber = "0.3" [build-dependencies] version_check = "0.9.5" # used where logic has to be version/distribution specific, e.g. pypy -pyo3-build-config = { version = "0.19.0" } \ No newline at end of file +pyo3-build-config = { version = "0.19.0" } From daf94e3085e573d880e3308c0ab4194f72efb4bf Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Mon, 7 Oct 2024 16:52:34 -0400 Subject: [PATCH 4/5] enable time/io for tokio --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index b54becf..a62a44a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ fn rt() -> Handle { RT.get_or_init(|| { tokio::runtime::Builder::new_multi_thread() .worker_threads(1) + .enable_all() .build() .unwrap() }) From 9537eba0f38a6b8c546ad428c79d21694ab840f4 Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Tue, 8 Oct 2024 11:10:46 -0400 Subject: [PATCH 5/5] switch to oncelock --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a62a44a..8a7fdc9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,13 +4,13 @@ use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::{PyList, PyTuple}; use std::cell::{OnceCell, RefCell}; -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use tokio::runtime::{Handle, Runtime}; const LEGACY_TRANSACTION_CONTROL: i32 = -1; fn rt() -> Handle { - const RT: OnceCell = OnceCell::new(); + static RT: OnceLock = OnceLock::new(); RT.get_or_init(|| { tokio::runtime::Builder::new_multi_thread()