Repository: launchbadge/sqlx
File: sqlx-core/src/sqlite/connection/mod.rs (Rust)

Code before:

    pub fn create_collation(
        &mut self,
        name: &str,
        compare: impl Fn(&str, &str) -> Ordering + Send + Sync + 'static,
    ) -> Result<(), Error> {
        collation::create_collation(&self.handle, name, compare)
    }
}

impl Debug for SqliteConnection {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_struct("SqliteConnection").finish()
    }
}

impl Connection for SqliteConnection {
    type Database = Sqlite;

    type Options = SqliteConnectOptions;

    fn close(mut self) -> BoxFuture<'static, Result<(), Error>> {
        Box::pin(async move {
            self.statements.clear();
            self.statement.take();
            self.worker.shutdown().await
        })
    }

    fn ping(&mut self) -> BoxFuture<'_, Result<(), Error>> {
        // For SQLite connections, PING does effectively nothing
        Box::pin(future::ok(()))
    }

    fn begin(&mut self) -> BoxFuture<'_, Result<Transaction<'_, Self::Database>, Error>>
    where
        Self: Sized,
    {
        Transaction::begin(self)
    }

    fn cached_statements_size(&self) -> usize {
        self.statements.len()
    }

    fn clear_cached_statements(&mut self) -> BoxFuture<'_, Result<(), Error>> {
        Box::pin(async move {
            self.statements.clear();
            Ok(())
        })
    }

Review comment (suggestion):
If you make `StatementWorker::shutdown()` work like `StatementWorker::reset()` does and have it send the message synchronously and return the receiver as `impl Future`, then instead of `.await`ing it directly, you could do something like:

```rust
let fut = self.worker.shutdown();

// drop the database handle
drop(self);

// wait for the statement worker to exit
fut.await
```

Code after:

    pub fn create_collation(
        &mut self,
        name: &str,
        compare: impl Fn(&str, &str) -> Ordering + Send + Sync + 'static,
    ) -> Result<(), Error> {
        collation::create_collation(&self.handle, name, compare)
    }
}

impl Debug for SqliteConnection {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_struct("SqliteConnection").finish()
    }
}

impl Connection for SqliteConnection {
    type Database = Sqlite;

    type Options = SqliteConnectOptions;

    fn close(mut self) -> BoxFuture<'static, Result<(), Error>> {
        Box::pin(async move {
            let shutdown = self.worker.shutdown();
            // Drop the statement worker and any outstanding statements, which should
            // cover all references to the connection handle outside of the worker thread
            drop(self);
            // Ensure the worker thread has terminated
            shutdown.await
        })
    }

    fn ping(&mut self) -> BoxFuture<'_, Result<(), Error>> {
        // For SQLite connections, PING does effectively nothing
        Box::pin(future::ok(()))
    }

    fn begin(&mut self) -> BoxFuture<'_, Result<Transaction<'_, Self::Database>, Error>>
    where
        Self: Sized,
    {
        Transaction::begin(self)
    }

    fn cached_statements_size(&self) -> usize {
        self.statements.len()
    }

    fn clear_cached_statements(&mut self) -> BoxFuture<'_, Result<(), Error>> {
        Box::pin(async move {
            self.statements.clear();