Ruben's January update: presenting Boost.MySQL's new pool!

Jan 10, 2024

In spite of it being winter here, Boost.MySQL is presenting a new pool this year! This was one of the most requested features in the library, and will finally be generally available as an experimental feature in Boost 1.85.

Connection pools manage tasks that are easy to get wrong, like reconnections, health checks and session cleanup. As they reuse physical connections, they also provide a nice efficiency boost.

Using a pool is as simple as:

boost::asio::awaitable<std::int64_t> get_num_employees(boost::mysql::connection_pool& pool)
{
   // Get a fresh connection from the pool
   auto conn = co_await pool.async_get_connection(boost::asio::use_awaitable);

   // Use the connection. It will be returned to the pool on scope exit
   results result;
   co_await conn->async_execute("SELECT COUNT(*) FROM employee", result, boost::asio::use_awaitable);
   co_return result.rows().at(0).at(0).as_int64();
}

Despite its simple interface, implementing connection_pool has been a long and hard task that has taken me a considerable effort. In the process, I’ve been able to learn in-depth many things about Boost.Asio which I thought I knew, but it turns out I did not.

For instance, I’ve finally understood the Asio property system, and wrote a blog post on it, hoping that others will find it easier to understand. I’ve also managed to make connection_pool easy to use in multi-threaded contexts using strands. I’ve found many subtle pitfalls here that are easy to get wrong. Thread-sanitizer for the win!

In any case, I’ve been able to get help from other knowledgeable Asio developers, both from inside and outside the C++ Alliance, which has been really helpful to get this done.

I’m also pretty happy with the role that Boost ServerTech chat has played in this task. ServerTech chat is a project to showcase how Boost libraries can be used together, and a place to innovate. Thanks to it, I’ve had an almost real-world environment to battle-test my API in.

Type-erased connections

With connection_pool, Boost.MySQL is getting a new type-erased connection type, any_connection, with much easier connection establishment semantics. Connection pooling relies on such semantics to provide better efficiency.

any_connection is currently experimental, but I expect it to become the default connection type once it becomes stable.

Boost.Redis finally released!

Boost.Redis finally got its first release with Boost 1.84. I’m proud to have helped the author integrate this library into Boost.

Boost integration is not a trivial process. Most novice authors only have CMake experience, but Boost builds require some parts to use B2. Even with CMake, some parts need to adhere to certain conventions to integrate with the Boost superproject. I’ve recently gone through this, so I’ve been able to help here.

I’m also pretty happy about my teammate’s efforts on documenting these processes in the contributor guide.

Sans-io all the things

Up to Boost 1.84, all network algorithms in Boost.MySQL are internally implemented as layered functions calling Boost.Asio primitives. As an overly simplistic example, connection::execute calls two functions, write_request and read_response, which end up in socket calls.

While this is the obvious way to implement such a library, it generates a lot of duplication. There is connection::execute and connection::async_execute, which yields two versions of every underlying function. It’s also slow to compile (Asio async code is full of heavy templates) and hard to test.

Starting from Boost 1.85, all network algorithms are implemented as state machines. Such algorithms are called sans-io, because they don’t directly invoke any I/O functions. A thin layer of Asio code connects such algorithms to I/O, yielding the same interface as before. These algorithms are currently an implementation detail, and not exposed to the public. This change has made the library much simpler and enjoyable to test. Even if you’re not planning to support sync functions, consider going sans-io - your unit tests will thank you.

Next steps: SQL query formatting

The next big step is supporting client-side query composition. This makes use cases like dynamic filters much easier to implement, and can increase efficiency by saving round-trips to the server. I’m currently examining the great fmt library as a source of inspiration.

All Posts by This Author