Diesel Async 0.4

I'm happy to announce the release of diesel-async 0.4.. This release includes two new features. It improves the configurability of our connection pooling solutions. In addition to these enhancements, this version also introduces a new feature that allows users to transform an async diesel_async::AsyncConnection into a sync diesel::Connection. To support future development efforts, please consider sponsoring me on GitHub. I would like to extend a sincere thank you to all our generous sponsors who have contributed to making this release possible.

Configuration for Connection Checking by Connection Pools

Prior to version 0.4 of diesel-async, checking out a connection from the connection pool always resulted in a check involving a simple query to verify that an existing connection from the pool was usable. This check would discard the connection if it failed. Diesel-async 0.4 enables users to customise this behaviour according to their specific needs via the RecyclingMethod enum. It offers the following variants:

  • Fast: This method only performs a local check to ensure that there are no open transactions on the existing connection. It is suitable for most use cases, particularly when working with local databases.
  • Verified: In addition to the checks performed by Fast, this variant also includes a simple test query to determine if the connection is still usable. This remains the default behaviour if no other variant is specified.
  • CustomQuery(Cow<'static, str>): With this method, you can execute a custom query instead of the test query used in the Verified variant. This allows for more fine-grained control over actual query performed.
  • CustomFunction(Box<dyn Fn(&mut C) -> BoxFuture<'_, QueryResult<()>>): This method enables you to provide a custom closure that will be called in addition to the checks provided by the Fast variant. This allows for even more tailored connection checking behavior based on your specific needs and requirements.

Depending on your use case you might prefer one or the other configuration. For local database the Fast checking method is usually sufficient, while for possibly problematic network connections the Verified variant can be useful. Both Custom* variants allow to adjust the checking for custom needs.

Example usage:

use diesel_async::pooled_connection::{AsyncDieselConnectionManager, ManagerConfig, RecyclingMethod};
use diesel_async::pooled_connection::deadpool::Pool;

// setup the connection pool configuration
let manager_config = ManagerConfig::default();
// use the `Fast` recycling configuration
manager_config.recycling_method = RecyclingMethod::Fast;

// create the pool manager
let config = AsyncDieselConnectionManager::<diesel_async::AsyncPgConnection>::new_with_config(
    db_url, manager_config
);
// create the connection pool
let pool = Pool::builder(config).build()?;

Async Connection Wrapper

Diesel-async 0.4 introduces an AsyncConnectionWrapper type that transforms an existing async diesel_async::AsyncConnection into a sync diesel::Connection. This new feature serves several purposes, despite the fact that diesel-async is designed to work with asynchronous connections:

With the addition of this sync connection wrapper, users can now take advantage of the pure rust database connection implementations in both async and sync contexts. However, it is important to note that switching from existing diesel connections to the new AsyncConnectionWrapper may not be recommendable at this point due to the novelty of the implementation.

Moreover, there are differences between the provided connection wrapper and existing diesel connection types in terms of functionality and behavior. These discrepancies include variations in handling database URL's, TLS configurations, and row streaming from the database. As a result the new connection type is not supposed to be a drop in replacement for existing diesel connection types.

Lastly, diesel-async prior to version 0.4 did not provide any means to utilize the diesel_migrations crate, as that library expects a sync Diesel connection implementation. By introducing the sync connection wrapper on top of existing async connection implementations, developers can now leverage the pure rust connection to execute migrations. Migrations are typically applied at application startup, and there is rarely a need for a distinct non-blocking variant in this context, as the application must wait until migrations have been successfully applied.

This feature is gated by the async-connection-wrapper feature.

Example usage:

use schema::users;
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
use diesel::prelude::{RunQueryDsl, Connection};

pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();

let mut conn = AsyncConnectionWrapper::<DbConnection>::establish(&database_url)?;
// apply migrations
conn.run_pending_migrations(MIGRATIONS)?;
// run queries using the sync `RunQueryDsl` implementation provided by diesel
let all_users = users::table.load::<(i32, String)>(&mut conn)?;