OZO 「お象」
Boost.Asio and libpq based asynchronous PostgreSQL unofficial header-only C++17 client library.
Strategy interface

Description

Failover microframwork strategy extention interface.

Classes

struct  ozo::failover::basic_context< ConnectionProvider, TimeConstraint, Args >
 Basic operation context. More...
 

Functions

template<typename FailoverStrategy , typename Operation , typename Allocator , typename ... Args>
auto ozo::failover::get_first_try (const Operation &op, const FailoverStrategy &strategy, const Allocator &alloc, Args &&...args)
 Get the first try object for an operation. More...
 
template<typename FailoverTry >
auto ozo::failover::get_try_context (const FailoverTry &a_try)
 Get operation context for the try. More...
 
template<typename Try , typename Connection >
auto ozo::failover::get_next_try (Try &a_try, const error_code &ec, Connection &conn)
 Get the next try object. More...
 
template<typename Try , typename Connection , typename Initiator >
auto ozo::failover::initiate_next_try (Try &a_try, const error_code &ec, Connection &conn, Initiator &&init)
 Initiates the next try of an operation execution. More...
 

Variables

template<typename T >
constexpr auto ozo::FailoverStrategy
 FailoverStrategy concept. More...
 
template<typename T >
constexpr auto ozo::FailoverTry
 FailoverTry concept. More...
 

Function Documentation

◆ get_first_try()

template<typename FailoverStrategy , typename Operation , typename Allocator , typename ... Args>
auto ozo::failover::get_first_try ( const Operation &  op,
const FailoverStrategy &  strategy,
const Allocator &  alloc,
Args &&...  args 
)

Get the first try object for an operation.

This function is a part of failover strategy interface. It creates the first try of operation execution context. The context data should be allocated via the specified allocator. This function would be called once during a failover operation execution. By default #FailoverStrategy should have get_first_try(const Operation& op, const Allocator& alloc, Args&& ...args) const member function.

Parameters
op— operation for which the try object should be created.
strategy— strategy according to which the try object should be created.
alloc— allocator for try object.
args— operation arguments except CompletionToken.
Returns
#FailoverTry object.

Customization Point

This function may be customized for a #FailoverStrategy via specialization of ozo::failover::get_first_try_impl. E.g.:

namespace ozo::failover {
template <typename Operation>
struct get_first_try_impl<my_strategy, Operation> {
template <typename Allocator, typename ...Args>
static auto apply(const Operation&, const my_strategy& s, const Allocator& alloc, Args&& ...args) {
return s.get_start_context<Operation>(alloc, std::forward<Args>(args)...);
}
};
} // namespace ozo::failover

◆ get_next_try()

template<typename Try , typename Connection >
auto ozo::failover::get_next_try ( Try &  a_try,
const error_code ec,
Connection conn 
)

Get the next try object.

Return #FailoverTry for next failover try if it possible. By default it calls a_try.get_next_try(ec, conn). This behavior customisable via ozo::failover::get_next_try_impl specialization. It will be used by default if no ozo::failover::initiate_next_try customization had been made.

Parameters
a_try— current #FailoverTry object.
ec— current try error code.
conn— current #connection object.
Returns
#FailoverTry — if given error code and connection may be failovered with next try.
null-state — otherwise.

Customization Point

This function may be customized for a #FailoverTry via specialization of ozo::failover::get_next_try_impl. E.g.:

namespace ozo::failover {
template <>
struct get_next_try_impl<my_strategy_try> {
template <typename Allocator, typename ...Args>
static std::optional<my_strategy_try> apply(const my_strategy_try& obj, error_code ec, Conn&& conn) {
if (ec != my_error_condition::recoverable) {
obj.log_error("can not recover error {0} with message {1}", ec, ozo::error_message(conn));
return std::nullopt;
}
obj.log_notice("recovering error {0} with message {1}", ec, ozo::error_message(conn));
return obj;
}
};
} // namespace ozo::failover

References ozo::unwrap().

◆ get_try_context()

template<typename FailoverTry >
auto ozo::failover::get_try_context ( const FailoverTry &  a_try)

Get operation context for the try.

By default #FailoverTry object should have get_context() const member function.

Parameters
a_try— #FailoverTry object
Returns
auto — #HanaSequence with operation arguments.

Customization Point

This function may be customized for a #FailoverTry via specialization of ozo::failover::get_try_context_impl. E.g.:

namespace ozo::failover {
template <>
struct get_try_context_impl<my_strategy_try> {
template <typename Allocator, typename ...Args>
static auto apply(const my_strategy_try& obj) {
return obj.ctx;
}
};
} // namespace ozo::failover

References ozo::unwrap().

◆ initiate_next_try()

template<typename Try , typename Connection , typename Initiator >
auto ozo::failover::initiate_next_try ( Try &  a_try,
const error_code ec,
Connection conn,
Initiator &&  init 
)

Initiates the next try of an operation execution.

This mechanism supports static polymorphism of tries depended on error conditions. Unlike ozo::failover::get_next_try() it allows to use different types of try-objects for different error conditions.

Function implementation should call initiator in case of operation with given error condition may be recovered by try-object is given to initiator. Or should not call initiator in case of an unrecoverable error condition.

Note
Initiator object should be called only once and should not be called out of the function scope since it contains references on stack-allocated objects.
Parameters
a_try— current #FailoverTry object.
ec— current try error code.
conn— current #connection object.
init— initiator of an operation execution, functional object with signature void(auto try)

Customization Point

This function may be customized for a #FailoverTry via specialization of ozo::failover::initiate_next_try_impl. E.g. default implementation may look like this:

namespace ozo::failover {
template <typename Try>
struct initiate_next_try_impl {
template <typename Connection, typename Initiator>
static auto apply(Try& a_try, const error_code& ec, Connection& conn, Initiator init) {
if (auto next = get_next_try(a_try, ec, conn); !is_null(next)) {
init(std::move(next));
}
}
};
} // namespace ozo::failover

References ozo::unwrap().

Variable Documentation

◆ FailoverStrategy

template<typename T >
constexpr auto ozo::FailoverStrategy
constexpr

FailoverStrategy concept.

Failover strategy defines interface for the failover framework extention. FailoverStrategy should be a factory for the first #FailoverTry.

Failover Compatible Operation

#include <boost/asio/spawn.hpp>
struct complex_transaction_data {
//...
};
template <typename Initiator>
struct complex_transaction_op : base_async_operation <complex_transaction_op, Initiator> {
using base = typename complex_transaction_op::base;
using base::base;
template <typename P, typename TimeConstraint, typename CompletionToken>
decltype(auto) operator() (P&& provider, complex_transaction_data data, TimeConstraint t, CompletionToken&& token) const {
static_assert(ozo::ConnectionProvider<P>, "provider should be a ConnectionProvider");
static_assert(ozo::TimeConstraint<TimeConstraint>, "should model TimeConstraint concept");
return ozo::async_initiate<CompletionToken, ozo::handler_signature<P>>(
// Initiator and token
get_operation_initiator(*this), token,
// ConnectionProvider, TimeConstraint, additional arguments
std::forward<P>(provider), ozo::deadline(t), std::move(data)
);
}
};
namespace detail {
template <typename Handler, typename TimeConstraint>
struct complex_transaction_impl {
complex_transaction_data data_;
TimeConstraint time_constraint_;
Handler handler_;
template <typename Connection>
constexpr void operator()(error_code ec, Connection&& conn) {
if (ec) {
return handler_(ec, std::forward<Connection>(conn));
}
boost::asio::spawn(ozo::get_executor(conn), [
data = std::move(data_),
time_constraint = std::move(time_constraint_),
handler = std::move(handler_)] (auto yield) mutable {
ozo::rows_of<...> rows;
auto conn = ozo::request(conn, time_constraint_, "..."_SQL..., ozo::into(rows), yield[ec]);
if (!ec) {
conn = ozo::execute(conn, time_constraint_, "..."_SQL + handle_data(rows)..., yield[ec]);
if (!ec) {
return ozo::commit(conn, std::move(handler_));
}
}
auto ex = boost::asio::get_associated_executor(handler_);
boost::asio::dispatch(ex, [ec, handler=std::move(handler_), conn = std::move(conn)]{
handler(ec, std::move(conn));
});
});
}
using executor_type = decltype(asio::get_associated_executor(handler_));
executor_type get_executor() const noexcept {
return asio::get_associated_executor(handler_);
}
using allocator_type = decltype(asio::get_associated_allocator(handler_));
allocator_type get_allocator() const noexcept {
return asio::get_associated_allocator(handler_);
}
};
struct initiate_complex_transaction {
template <typename Handler, typename P, typename Q, typename TimeConstraint>
constexpr void operator()(Handler&& h, P&& provider, TimeConstraint t, complex_transaction_data data) const {
ozo::begin(provider, t, complex_transaction_impl{std::move(data), t, std::forward<Handler>(h)});
}
};
} // namespace detail
constexpr complex_transaction_op<detail::initiate_async_execute> complex_transaction;

◆ FailoverTry

template<typename T >
constexpr auto ozo::FailoverTry
constexpr

FailoverTry concept.

Failover try defines interface for a single operation execution try and possible next failover try.

ozo::request
decltype(auto) request(ConnectionProvider &&provider, BinaryQueryConvertible &&query, TimeConstraint time_constraint, Out out, CompletionToken &&token)
Executes query and retrives a result from a database with time constraint.
ozo::error_code
boost::system::error_code error_code
Error code representation of the library.
Definition: error.h:38
ozo::deadline
constexpr time_traits::time_point deadline(time_traits::time_point t) noexcept
Dealdine calculation.
Definition: deadline.h:16
ozo::error_message
std::string_view error_message(const Connection &conn)
Get native libpq error message.
Definition: connection.h:97
ozo::get_executor
auto get_executor(const Connection &conn) noexcept
Get the executor associated with the object.
Definition: connection.h:130
ozo::rows_of
std::vector< typed_row< Ts... > > rows_of
Shortcut for easy result container definition.
Definition: shortcuts.h:37
ozo::into
constexpr auto into(T &v)
Shortcut for create result container back inserter.
Definition: shortcuts.h:85
ozo::execute
decltype(auto) execute(ConnectionProvider &&provider, BinaryQueryConvertible &&query, TimeConstraint time_constraint, CompletionToken &&token)
Executes query with no result data expected.
ozo::get_operation_initiator
constexpr auto get_operation_initiator(const Operation &op)
Get asynchronous operation initiator.
Definition: asio.h:166
ozo::begin
decltype(auto) begin(ConnectionProvider &&provider, TimeConstraint time_constraint, CompletionToken &&token)
Start new transaction.
CompletionToken
Completion token concept.
Handler
Handler concept.
ozo::is_null
constexpr decltype(auto) is_null(const T &v) noexcept(noexcept(is_null_impl< T >::apply(v)))
Indicates if value is in null state.
Definition: nullable.h:85
ozo::failover::get_next_try
auto get_next_try(Try &a_try, const error_code &ec, Connection &conn)
Get the next try object.
Definition: strategy.h:306
Connection
Database connection concept.
ozo::commit
decltype(auto) commit(transaction< T, Options > &&transaction, TimeConstraint t, CompletionToken &&token)
Commits a transaction.