SQLite: Fix thread pool exhaustion

This commit is contained in:
mdecimus
2026-02-25 14:33:52 +01:00
parent d340e7d469
commit c3586d9af6
5 changed files with 38 additions and 32 deletions

View File

@@ -16,8 +16,9 @@ impl SqliteStore {
key: &[u8],
range: Range<usize>,
) -> trc::Result<Option<Vec<u8>>> {
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
let mut result = conn
.prepare_cached("SELECT v FROM t WHERE k = ?")
.map_err(into_error)?;
@@ -42,8 +43,9 @@ impl SqliteStore {
}
pub(crate) async fn put_blob(&self, key: &[u8], data: &[u8]) -> trc::Result<()> {
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
conn.prepare_cached("INSERT OR REPLACE INTO t (k, v) VALUES (?, ?)")
.map_err(into_error)?
.execute([key, data])
@@ -54,8 +56,9 @@ impl SqliteStore {
}
pub(crate) async fn delete_blob(&self, key: &[u8]) -> trc::Result<bool> {
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
conn.prepare_cached("DELETE FROM t WHERE k = ?")
.map_err(into_error)?
.execute([key])

View File

@@ -16,8 +16,9 @@ impl SqliteStore {
query: &str,
params_: &[Value<'_>],
) -> trc::Result<T> {
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
let mut s = conn.prepare_cached(query).map_err(into_error)?;
let params = params_
.iter()

View File

@@ -79,6 +79,7 @@ impl SqliteStore {
SUBSPACE_TELEMETRY_SPAN,
SUBSPACE_TELEMETRY_METRIC,
SUBSPACE_SEARCH_INDEX,
SUBSPACE_DIRECTORY,
] {
let table = char::from(table);
conn.execute(
@@ -93,16 +94,22 @@ impl SqliteStore {
.map_err(into_error)?;
}
let table = char::from(SUBSPACE_INDEXES);
conn.execute(
&format!(
"CREATE TABLE IF NOT EXISTS {table} (
for table in [
SUBSPACE_INDEXES,
SUBSPACE_REGISTRY_IDX,
SUBSPACE_REGISTRY_IDX_GLOBAL,
] {
let table = char::from(table);
conn.execute(
&format!(
"CREATE TABLE IF NOT EXISTS {table} (
k BLOB PRIMARY KEY
)"
),
[],
)
.map_err(into_error)?;
),
[],
)
.map_err(into_error)?;
}
for table in [SUBSPACE_COUNTER, SUBSPACE_QUOTA, SUBSPACE_IN_MEMORY_COUNTER] {
conn.execute(

View File

@@ -13,8 +13,9 @@ impl SqliteStore {
where
U: Deserialize + 'static,
{
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
let mut result = conn
.prepare_cached(&format!(
"SELECT v FROM {} WHERE k = ?",
@@ -24,7 +25,7 @@ impl SqliteStore {
let key = key.serialize(0);
result
.query_row([&key], |row| {
U::deserialize(row.get_ref(0)?.as_bytes()?)
U::deserialize_with_key(&key, row.get_ref(0)?.as_bytes()?)
.map_err(|err| rusqlite::Error::ToSqlConversionFailure(err.into()))
})
.optional()
@@ -38,9 +39,9 @@ impl SqliteStore {
params: IterateParams<T>,
mut cb: impl for<'x> FnMut(&'x [u8], &'x [u8]) -> trc::Result<bool> + Sync + Send,
) -> trc::Result<()> {
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
let table = char::from(params.begin.subspace());
let begin = params.begin.serialize(0);
let end = params.end.serialize(0);
@@ -113,8 +114,9 @@ impl SqliteStore {
let key = key.into();
let table = char::from(key.subspace());
let key = key.serialize(0);
let conn = self.conn_pool.get().map_err(into_error)?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
match conn
.prepare_cached(&format!("SELECT v FROM {table} WHERE k = ?"))
.map_err(into_error)?

View File

@@ -14,12 +14,10 @@ use trc::AddContext;
impl SqliteStore {
pub(crate) async fn write(&self, batch: Batch<'_>) -> trc::Result<AssignedIds> {
let mut conn = self
.conn_pool
.get()
.map_err(into_error)
.caused_by(trc::location!())?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let mut conn = manager.get().map_err(into_error)?;
let mut account_id = u32::MAX;
let mut collection = u8::MAX;
let mut document_id = u32::MAX;
@@ -271,12 +269,9 @@ impl SqliteStore {
}
pub(crate) async fn purge_store(&self) -> trc::Result<()> {
let conn = self
.conn_pool
.get()
.map_err(into_error)
.caused_by(trc::location!())?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
for subspace in [SUBSPACE_QUOTA, SUBSPACE_COUNTER, SUBSPACE_IN_MEMORY_COUNTER] {
conn.prepare_cached(&format!("DELETE FROM {} WHERE v = 0", char::from(subspace),))
.map_err(into_error)
@@ -292,12 +287,10 @@ impl SqliteStore {
}
pub(crate) async fn delete_range(&self, from: impl Key, to: impl Key) -> trc::Result<()> {
let conn = self
.conn_pool
.get()
.map_err(into_error)
.caused_by(trc::location!())?;
let manager = self.conn_pool.clone();
self.spawn_worker(move || {
let conn = manager.get().map_err(into_error)?;
conn.prepare_cached(&format!(
"DELETE FROM {} WHERE k >= ? AND k < ?",
char::from(from.subspace()),