sql: replace .get_conn() interface with .call()

.call() interface is safer because it ensures
that blocking operations on SQL connection
are called within tokio::task::block_in_place().

Previously some code called blocking operations
in async context, e.g. add_parts() in receive_imf module.

The underlying implementation of .call()
can later be replaced with an implementation
that does not require block_in_place(),
e.g. a worker pool,
without changing the code using the .call() interface.
This commit is contained in:
link2xt
2023-02-18 13:50:44 +00:00
parent 710cec1beb
commit 92c7cc40d4
8 changed files with 189 additions and 171 deletions

View File

@@ -601,32 +601,38 @@ pub(crate) async fn save(
..
} = location;
let conn = context.sql.get_conn().await?;
let mut stmt_test =
conn.prepare_cached("SELECT id FROM locations WHERE timestamp=? AND from_id=?")?;
let mut stmt_insert = conn.prepare_cached(stmt_insert)?;
context
.sql
.call(|conn| {
let mut stmt_test = conn
.prepare_cached("SELECT id FROM locations WHERE timestamp=? AND from_id=?")?;
let mut stmt_insert = conn.prepare_cached(stmt_insert)?;
let exists = stmt_test.exists(paramsv![timestamp, contact_id])?;
let exists = stmt_test.exists(paramsv![timestamp, contact_id])?;
if independent || !exists {
stmt_insert.execute(paramsv![
timestamp,
contact_id,
chat_id,
latitude,
longitude,
accuracy,
independent,
])?;
if independent || !exists {
stmt_insert.execute(paramsv![
timestamp,
contact_id,
chat_id,
latitude,
longitude,
accuracy,
independent,
])?;
if timestamp > newest_timestamp {
// okay to drop, as we use cached prepared statements
drop(stmt_test);
drop(stmt_insert);
newest_timestamp = timestamp;
newest_location_id = Some(u32::try_from(conn.last_insert_rowid())?);
}
}
if timestamp > newest_timestamp {
// okay to drop, as we use cached prepared statements
drop(stmt_test);
drop(stmt_insert);
newest_timestamp = timestamp;
newest_location_id = Some(u32::try_from(conn.last_insert_rowid())?);
}
}
Ok(())
})
.await?;
}
Ok(newest_location_id)