Initial functions for using sqlite in async environment

[?]
Dec 23, 2021, 8:06 PM
AV73DYWQ2UVZJYTN3UIW3TDMWNAETLXZRD7VHKTQLFQGHKJ5KI6QC

Dependencies

Change contents

  • file addition: names_database.rs (----------)
    [2.15]
    use tokio::sync::{mpsc, oneshot};
    fn create_tables(conn: &sqlite::Connection) -> sqlite::Result<()> {
    conn.execute("CREATE TABLE IF NOT EXISTS names (name TEXT)")?;
    conn.execute(
    "CREATE TABLE IF NOT EXISTS preferences (
    better INTEGER,
    worse INTEGER,
    FOREIGN KEY (better) REFERENCES names(rowid) ON DELETE CASCADE,
    FOREIGN KEY (worse) REFERENCES names(rowid) ON DELETE CASCADE,
    UNIQUE(better,worse))",
    )?;
    Ok(())
    }
    struct AsyncConnection(
    mpsc::Sender<Box<dyn for<'a> FnOnce(&'a sqlite::Connection) + Send>>,
    );
    impl AsyncConnection {
    pub async fn open<T: AsRef<std::path::Path> + Send + 'static>(
    path: T,
    ) -> Result<Self, Box<dyn std::error::Error>> {
    let (tx, mut rx): (
    _,
    mpsc::Receiver<Box<dyn for<'a> FnOnce(&sqlite::Connection) + Send>>,
    ) = mpsc::channel(1);
    std::thread::Builder::new()
    .name(format!("database thread: {}", path.as_ref().display()))
    .spawn(move || {
    let conn = sqlite::open(path).unwrap();
    while let Some(cb) = rx.blocking_recv() {
    cb(&conn);
    }
    })?;
    let result = Self(tx);
    result.post(create_tables).await??;
    Ok(result)
    }
    async fn post<
    F: FnOnce(&sqlite::Connection) -> U + Send + 'static,
    U: Send + 'static,
    >(
    &self,
    cb: F,
    ) -> Result<U, Box<dyn std::error::Error>> {
    let (sc, rc): (_, oneshot::Receiver<U>) = oneshot::channel();
    self.0
    .send(Box::new(move |conn: &sqlite::Connection| {
    sc.send(cb(conn)).unwrap_or(());
    })
    as Box<dyn for<'a> FnOnce(&'a sqlite::Connection) + Send>)
    .await
    .map_err(|mpsc::error::SendError(_)| mpsc::error::SendError(()))?;
    Ok(rc.await?)
    }
    }
  • replacement in src/main.rs at line 1
    [2.49][2.50:62]()
    fn main() {
    [2.49]
    [2.62]
    mod names_database;
    #[tokio::main]
    async fn main() {
  • file addition: rustfmt.toml (----------)
    [4.1]
    max_width = 80
  • replacement in Cargo.toml at line 12
    [2.367][2.367:433]()
    tokio = { version = "1.15.0", features = ["macros","sync","rt"] }
    [2.367]
    tokio = { version = "1.15.0", features = ["macros","sync","rt-multi-thread"] }
  • edit in Cargo.lock at line 289
    [2.8194]
    [2.8194]
    [[package]]
    name = "hermit-abi"
    version = "0.1.19"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
    dependencies = [
    "libc",
    ]
  • edit in Cargo.lock at line 578
    [2.15020]
    [2.15020]
    ]
    [[package]]
    name = "num_cpus"
    version = "1.13.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
    dependencies = [
    "hermit-abi",
    "libc",
  • edit in Cargo.lock at line 1204
    [2.30147]
    [2.30147]
    "num_cpus",