libpqxx  7.9.0
transactor.hxx
1 /* Transactor framework, a wrapper for safely retryable transactions.
2  *
3  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/transactor instead.
4  *
5  * Copyright (c) 2000-2024, Jeroen T. Vermeulen.
6  *
7  * See COPYING for copyright license. If you did not receive a file called
8  * COPYING with this source code, please notify the distributor of this
9  * mistake, or contact the author.
10  */
11 #ifndef PQXX_H_TRANSACTOR
12 #define PQXX_H_TRANSACTOR
13 
14 #if !defined(PQXX_HEADER_PRE)
15 # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
16 #endif
17 
18 #include <functional>
19 #include <type_traits>
20 
21 #include "pqxx/connection.hxx"
22 #include "pqxx/transaction.hxx"
23 
24 namespace pqxx
25 {
69 
71 
100 template<typename TRANSACTION_CALLBACK>
101 inline auto perform(TRANSACTION_CALLBACK &&callback, int attempts = 3)
102  -> std::invoke_result_t<TRANSACTION_CALLBACK>
103 {
104  if (attempts <= 0)
105  throw std::invalid_argument{
106  "Zero or negative number of attempts passed to pqxx::perform()."};
107 
108  for (; attempts > 0; --attempts)
109  {
110  try
111  {
112  return std::invoke(callback);
113  }
114  catch (in_doubt_error const &)
115  {
116  // Not sure whether transaction went through or not. The last thing in
117  // the world that we should do now is try again!
118  throw;
119  }
120  catch (statement_completion_unknown const &)
121  {
122  // Not sure whether our last statement succeeded. Don't risk running it
123  // again.
124  throw;
125  }
126  catch (protocol_violation const &)
127  {
128  // This is a subclass of broken_connection, but it's not one where
129  // retrying is likely to do us any good.
130  throw;
131  }
132  catch (broken_connection const &)
133  {
134  // Connection failed. May be worth retrying, if the transactor opens its
135  // own connection.
136  if (attempts <= 1)
137  throw;
138  continue;
139  }
140  catch (transaction_rollback const &)
141  {
142  // Some error that may well be transient, such as serialization failure
143  // or deadlock. Worth retrying.
144  if (attempts <= 1)
145  throw;
146  continue;
147  }
148  }
149  throw pqxx::internal_error{"No outcome reached on perform()."};
150 }
151 } // namespace pqxx
153 #endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:33
auto perform(TRANSACTION_CALLBACK &&callback, int attempts=3) -> std::invoke_result_t< TRANSACTION_CALLBACK >
Simple way to execute a transaction with automatic retry.
Definition: transactor.hxx:101
Exception class for lost or failed backend connection.
Definition: except.hxx:81
Exception class for micommunication with the server.
Definition: except.hxx:103
"Help, I don't know whether transaction was committed successfully!"
Definition: except.hxx:165
The backend saw itself forced to roll back the ongoing transaction.
Definition: except.hxx:178
We can't tell whether our last statement succeeded.
Definition: except.hxx:214
Internal error in libpqxx library.
Definition: except.hxx:242