/* Definition of the pqxx::robusttransaction class. * * pqxx::robusttransaction is a slower but safer transaction class. * * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/robusttransaction instead. * * Copyright (c) 2000-2022, Jeroen T. Vermeulen. * * See COPYING for copyright license. If you did not receive a file called * COPYING with this source code, please notify the distributor of this * mistake, or contact the author. */ #ifndef PQXX_H_ROBUSTTRANSACTION #define PQXX_H_ROBUSTTRANSACTION #if !defined(PQXX_HEADER_PRE) # error "Include libpqxx headers as , not ." #endif #include "pqxx/dbtransaction.hxx" namespace pqxx::internal { /// Helper base class for the @ref robusttransaction class template. class PQXX_LIBEXPORT PQXX_NOVTABLE basic_robusttransaction : public dbtransaction { public: virtual ~basic_robusttransaction() override = 0; protected: basic_robusttransaction( connection &c, zview begin_command, std::string_view tname); basic_robusttransaction(connection &c, zview begin_command); private: using IDType = unsigned long; std::string m_conn_string; std::string m_xid; int m_backendpid = -1; void init(zview begin_command); // @warning This function will become `final`. virtual void do_commit() override; }; } // namespace pqxx::internal namespace pqxx { /** * @ingroup transactions * * @{ */ /// Slightly slower, better-fortified version of transaction. /** Requires PostgreSQL 10 or better. * * robusttransaction is similar to transaction, but spends more time and effort * to deal with the hopefully rare case that the connection to the backend is * lost just while it's trying to commit. In such cases, the client does not * know whether the backend (on the other side of the broken connection) * managed to commit the transaction. * * When this happens, robusttransaction tries to reconnect to the database and * figure out what happened. * * This service level was made optional since you may not want to pay the * overhead where it is not necessary. Certainly the use of this class makes * no sense for local connections, or for transactions that read the database * but never modify it, or for noncritical database manipulations. * * Besides being slower, it's also more complex. Which means that in practice * a robusttransaction could actually fail more instead of less often than a * normal transaction. What robusttransaction tries to achieve is to give you * certainty, not just be more successful per se. */ template class robusttransaction final : public internal::basic_robusttransaction { public: /** Create robusttransaction of given name. * @param c Connection inside which this robusttransaction should live. * @param tname optional human-readable name for this transaction. */ robusttransaction(connection &c, std::string_view tname) : internal::basic_robusttransaction{ c, pqxx::internal::begin_cmd, tname} {} /** Create robusttransaction of given name. * @param c Connection inside which this robusttransaction should live. * @param tname optional human-readable name for this transaction. */ robusttransaction(connection &c, std::string &&tname) : internal::basic_robusttransaction{ c, pqxx::internal::begin_cmd, std::move(tname)} {} /** Create robusttransaction of given name. * @param c Connection inside which this robusttransaction should live. */ explicit robusttransaction(connection &c) : internal::basic_robusttransaction{ c, pqxx::internal::begin_cmd} {} virtual ~robusttransaction() noexcept override { close(); } }; /** * @} */ } // namespace pqxx #endif