Skip to content

Commit

Permalink
Error handling fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
anarthal committed Nov 20, 2024
1 parent 9bbf393 commit a684791
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 8 deletions.
12 changes: 5 additions & 7 deletions doc/qbk/03_7_tutorial_error_handling.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ Why are we not seeing the error code?

When an awaitable in Asio is co_await'ed, the first handler argument is inspected.
If it's an `error_code` that indicates a failure, an exception is thrown.
The `error_code` is removed and not returned from the co_await expression,
thus seeing only `mysql::pooled_connection`.
The `error_code` is removed from the argument list,
leaving a `mysql::pooled_connection` only.

[asioreflink as_tuple as_tuple] is a completion token
that modifies the handler signature, packing all arguments into a `std::tuple`.
It's used similarly to the `asio::cancel_after` token we have learnt in the previous tutorial:
It's used similarly to the `asio::cancel_after` token that we used in the previous tutorial:

[tutorial_error_handling_get_connection_as_tuple]

Expand All @@ -67,9 +67,7 @@ In practice, it's usually better to use structured bindings:

[heading Using asio::as_tuple for database code]

An error when talking to the database implies only sending a special value to the client.
This means that the function encapsulating database logic can maintain its original signature.
Applying [asioreflink as_tuple as_tuple] yields:
If we apply [asioreflink as_tuple as_tuple] to our database logic, we have:

[tutorial_error_handling_db_nodiag]

Expand All @@ -89,7 +87,7 @@ When using error codes, we need to handle diagnostics manually.
All functions in Boost.MySQL are overloaded to accept a [reflink diagnostics]
output parameter. It will be populated with extra information in case of error.

Let's update our code to use it:
Let's update our code to use diagnostics:

[tutorial_error_handling_db]

Expand Down
2 changes: 2 additions & 0 deletions example/1_tutorial/7_error_handling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,15 @@ struct employee
//[tutorial_error_handling_db
asio::awaitable<std::string> get_employee_details(mysql::connection_pool& pool, std::int64_t employee_id)
{
// Will be populated with error information in case of error
mysql::diagnostics diag;

// Get a connection from the pool.
// This will wait until a healthy connection is ready to be used.
// pooled_connection grants us exclusive access to the connection until
// the object is destroyed
//[tutorial_error_handling_structured_bindings
// ec is an error_code, conn is the mysql::pooled_connection
auto [ec, conn] = co_await pool.async_get_connection(diag, asio::as_tuple);
//]
if (ec)
Expand Down
4 changes: 3 additions & 1 deletion test/integration/test/snippets/tutorials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,16 @@ asio::awaitable<void> tutorial_connection_pool_unused(
void log_error(const char*, boost::system::error_code) {}

// Version without diagnostics
// [tutorial_error_handling_db_nodiag
//[tutorial_error_handling_db_nodiag
asio::awaitable<std::string> get_employee_details(mysql::connection_pool& pool, std::int64_t employee_id)
{
// Get a connection from the pool.
// This will wait until a healthy connection is ready to be used.
auto [ec, conn] = co_await pool.async_get_connection(asio::as_tuple);
if (ec)
{
// A connection couldn't be obtained.
// This may be because the session timed out.
log_error("Error in async_get_connection", ec);
co_return "ERROR";
}
Expand Down

0 comments on commit a684791

Please sign in to comment.