Skip to content

Commit 0713706

Browse files
committed
feat mongo: transactions core
commit_hash:fbd68b0242bae6fb5e536b1ecbe1f89f76dbf83b
1 parent ac79c83 commit 0713706

26 files changed

+1038
-59
lines changed

.mapping.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3037,6 +3037,7 @@
30373037
"mongo/include/userver/storages/mongo/options.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/options.hpp",
30383038
"mongo/include/userver/storages/mongo/pool.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/pool.hpp",
30393039
"mongo/include/userver/storages/mongo/pool_config.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/pool_config.hpp",
3040+
"mongo/include/userver/storages/mongo/transaction.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/transaction.hpp",
30403041
"mongo/include/userver/storages/mongo/utest/mongo_fixture.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/utest/mongo_fixture.hpp",
30413042
"mongo/include/userver/storages/mongo/utest/mongo_local.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/utest/mongo_local.hpp",
30423043
"mongo/include/userver/storages/mongo/write_result.hpp":"taxi/uservices/userver/mongo/include/userver/storages/mongo/write_result.hpp",
@@ -3079,10 +3080,14 @@
30793080
"mongo/src/storages/mongo/cdriver/collection_impl.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/collection_impl.hpp",
30803081
"mongo/src/storages/mongo/cdriver/cursor_impl.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/cursor_impl.cpp",
30813082
"mongo/src/storages/mongo/cdriver/cursor_impl.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/cursor_impl.hpp",
3083+
"mongo/src/storages/mongo/cdriver/find_and_modify.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/find_and_modify.cpp",
3084+
"mongo/src/storages/mongo/cdriver/find_and_modify.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/find_and_modify.hpp",
30823085
"mongo/src/storages/mongo/cdriver/logger.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/logger.cpp",
30833086
"mongo/src/storages/mongo/cdriver/logger.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/logger.hpp",
30843087
"mongo/src/storages/mongo/cdriver/pool_impl.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/pool_impl.cpp",
30853088
"mongo/src/storages/mongo/cdriver/pool_impl.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/pool_impl.hpp",
3089+
"mongo/src/storages/mongo/cdriver/transaction_collection_impl.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/transaction_collection_impl.cpp",
3090+
"mongo/src/storages/mongo/cdriver/transaction_collection_impl.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/transaction_collection_impl.hpp",
30863091
"mongo/src/storages/mongo/cdriver/wrappers.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/wrappers.cpp",
30873092
"mongo/src/storages/mongo/cdriver/wrappers.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/cdriver/wrappers.hpp",
30883093
"mongo/src/storages/mongo/collection.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/collection.cpp",
@@ -3131,6 +3136,10 @@
31313136
"mongo/src/storages/mongo/stats_serialize.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/stats_serialize.hpp",
31323137
"mongo/src/storages/mongo/tcp_connect_precheck.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/tcp_connect_precheck.cpp",
31333138
"mongo/src/storages/mongo/tcp_connect_precheck.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/tcp_connect_precheck.hpp",
3139+
"mongo/src/storages/mongo/transaction.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/transaction.cpp",
3140+
"mongo/src/storages/mongo/transaction_impl.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/transaction_impl.cpp",
3141+
"mongo/src/storages/mongo/transaction_impl.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/transaction_impl.hpp",
3142+
"mongo/src/storages/mongo/transaction_mongotest.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/transaction_mongotest.cpp",
31343143
"mongo/src/storages/mongo/utest/mongo_local.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/utest/mongo_local.cpp",
31353144
"mongo/src/storages/mongo/util_mongotest.cpp":"taxi/uservices/userver/mongo/src/storages/mongo/util_mongotest.cpp",
31363145
"mongo/src/storages/mongo/util_mongotest.hpp":"taxi/uservices/userver/mongo/src/storages/mongo/util_mongotest.hpp",

mongo/include/userver/formats/bson/document.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class Document : public Value {
3030
/// @endcond
3131
};
3232

33+
void PrintTo(const Document& value, std::ostream* os);
34+
3335
} // namespace formats::bson
3436

3537
USERVER_NAMESPACE_END

mongo/include/userver/storages/mongo/bulk.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ USERVER_NAMESPACE_BEGIN
1111

1212
namespace storages::mongo::impl::cdriver {
1313
class CDriverCollectionImpl;
14+
class CDriverTransactionCollectionImpl;
1415
} // namespace storages::mongo::impl::cdriver
1516

1617
namespace storages::mongo::operations {
@@ -71,6 +72,7 @@ class Bulk {
7172

7273
private:
7374
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
75+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
7476

7577
class Impl;
7678
static constexpr size_t kSize = 56;

mongo/include/userver/storages/mongo/exception.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ class PoolOverloadException : public MongoException {
4747
using MongoException::MongoException;
4848
};
4949

50+
/// Transaction-related exception
51+
class TransactionException : public MongoException {
52+
public:
53+
enum class Type {
54+
kTransientError, ///< Transient error that may be retried
55+
kPermanentError, ///< Permanent error, cannot retry
56+
};
57+
58+
TransactionException(Type type, std::string_view what);
59+
60+
Type GetType() const noexcept { return type_; }
61+
62+
private:
63+
Type type_;
64+
};
65+
5066
/// Network (connectivity) error
5167
class NetworkException : public MongoException {
5268
public:

mongo/include/userver/storages/mongo/operations.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ USERVER_NAMESPACE_BEGIN
1212

1313
namespace storages::mongo::impl::cdriver {
1414
class CDriverCollectionImpl;
15+
class CDriverTransactionCollectionImpl;
1516
} // namespace storages::mongo::impl::cdriver
1617

1718
/// Collection operations
@@ -38,6 +39,7 @@ class Count {
3839

3940
private:
4041
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
42+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
4143

4244
class Impl;
4345
static constexpr size_t kSize = 96;
@@ -66,6 +68,7 @@ class CountApprox {
6668

6769
private:
6870
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
71+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
6972

7073
class Impl;
7174
static constexpr size_t kSize = 72;
@@ -100,6 +103,7 @@ class Find {
100103

101104
private:
102105
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
106+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
103107

104108
class Impl;
105109
static constexpr size_t kSize = 96;
@@ -125,6 +129,7 @@ class InsertOne {
125129

126130
private:
127131
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
132+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
128133

129134
class Impl;
130135
static constexpr size_t kSize = 80;
@@ -154,6 +159,7 @@ class InsertMany {
154159

155160
private:
156161
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
162+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
157163

158164
class Impl;
159165
static constexpr size_t kSize = 88;
@@ -180,6 +186,7 @@ class ReplaceOne {
180186

181187
private:
182188
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
189+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
183190

184191
class Impl;
185192
static constexpr size_t kSize = 96;
@@ -213,6 +220,7 @@ class Update {
213220

214221
private:
215222
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
223+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
216224

217225
class Impl;
218226
static constexpr size_t kSize = 96;
@@ -243,6 +251,7 @@ class Delete {
243251

244252
private:
245253
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
254+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
246255

247256
class Impl;
248257
static constexpr size_t kSize = 80;
@@ -274,8 +283,10 @@ class FindAndModify {
274283

275284
private:
276285
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
286+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
277287

278288
class Impl;
289+
FindAndModify(Impl&&);
279290
static constexpr size_t kSize = 80;
280291
static constexpr size_t kAlignment = 8;
281292
// MAC_COMPAT: std::string size differs
@@ -301,8 +312,10 @@ class FindAndRemove {
301312

302313
private:
303314
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
315+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
304316

305317
class Impl;
318+
FindAndRemove(Impl&&);
306319
static constexpr size_t kSize = 72;
307320
static constexpr size_t kAlignment = 8;
308321
// MAC_COMPAT: std::string size differs
@@ -331,6 +344,7 @@ class Aggregate {
331344

332345
private:
333346
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
347+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
334348

335349
class Impl;
336350
static constexpr size_t kSize = 120;
@@ -360,6 +374,7 @@ class Distinct final {
360374

361375
private:
362376
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
377+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
363378

364379
class Impl;
365380
static constexpr size_t kSize = 104;
@@ -383,6 +398,7 @@ class Drop {
383398

384399
private:
385400
friend class storages::mongo::impl::cdriver::CDriverCollectionImpl;
401+
friend class storages::mongo::impl::cdriver::CDriverTransactionCollectionImpl;
386402

387403
class Impl;
388404
static constexpr size_t kSize = 56;

mongo/include/userver/storages/mongo/pool.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <userver/dynamic_config/fwd.hpp>
1212
#include <userver/storages/mongo/collection.hpp>
1313
#include <userver/storages/mongo/pool_config.hpp>
14+
#include <userver/storages/mongo/transaction.hpp>
1415
#include <userver/utils/statistics/fwd.hpp>
1516
#include <userver/utils/zstring_view.hpp>
1617

@@ -55,6 +56,11 @@ class Pool {
5556
/// @throws storages::mongo::MongoException if failed to connect to the mongo server.
5657
void Ping();
5758

59+
/// @brief Begin a new transaction
60+
/// @return Transaction handle for executing operations within transaction context
61+
/// @throws MongoException if transaction cannot be started
62+
Transaction BeginTransaction() const;
63+
5864
/// @cond
5965
// For internal use only
6066
Pool(
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#pragma once
2+
3+
/// @file userver/storages/mongo/transaction.hpp
4+
/// @brief @copybrief storages::mongo::Transaction
5+
6+
#include <memory>
7+
#include <string>
8+
9+
#include <userver/storages/mongo/collection.hpp>
10+
#include <userver/storages/mongo/options.hpp>
11+
12+
USERVER_NAMESPACE_BEGIN
13+
14+
namespace storages::mongo {
15+
16+
namespace impl {
17+
class TransactionImpl;
18+
} // namespace impl
19+
20+
/// @brief MongoDB transaction handle that provides ACID guarantees.
21+
///
22+
/// Transactions group multiple operations within logical units of work
23+
/// and provide ACID guarantees. All operations in a transaction either
24+
/// succeed completely or fail completely.
25+
///
26+
/// ## Usage example:
27+
///
28+
/// @snippet mongo/src/storages/mongo/transaction_mongotest.cpp [transaction]
29+
///
30+
/// @note Transactions require MongoDB replica sets or sharded clusters.
31+
/// @note Operations within a transaction are automatically retried according
32+
/// to MongoDB transaction retry semantics.
33+
class Transaction {
34+
public:
35+
/// @brief Creates invalid transaction
36+
Transaction();
37+
38+
/// @cond
39+
// For internal use only.
40+
explicit Transaction(std::unique_ptr<impl::TransactionImpl>);
41+
/// @endcond
42+
43+
/// @brief Move constructor
44+
Transaction(Transaction&&) noexcept;
45+
46+
/// @brief Move assignment operator
47+
Transaction& operator=(Transaction&&) noexcept;
48+
49+
/// @brief Destructor. Aborts transaction if not committed.
50+
~Transaction();
51+
52+
/// @brief Get a collection handle within the transaction context
53+
/// @param name collection name
54+
/// @return Collection handle that operates within this transaction
55+
Collection GetCollection(std::string name);
56+
57+
/// @brief Commit the transaction
58+
///
59+
/// Makes all changes within the transaction permanent and visible
60+
/// to other operations. If the transaction fails to commit,
61+
/// an exception will be thrown.
62+
///
63+
/// @throws MongoException on commit failure
64+
void Commit();
65+
66+
/// @brief Abort the transaction
67+
///
68+
/// Discards all changes made within the transaction.
69+
/// This method is idempotent and safe to call multiple times.
70+
void Abort() noexcept;
71+
72+
/// @brief Check if transaction is active
73+
/// @return true if transaction is active (not committed or aborted)
74+
bool IsActive() const noexcept;
75+
76+
/// @brief Get the transaction state
77+
enum class State {
78+
kNone, ///< Transaction not started
79+
kInProgress, ///< Transaction is active
80+
kCommitted, ///< Transaction has been committed
81+
kAborted ///< Transaction has been aborted
82+
};
83+
84+
/// @brief Get current transaction state
85+
State GetState() const noexcept;
86+
87+
private:
88+
std::unique_ptr<impl::TransactionImpl> impl_;
89+
};
90+
91+
} // namespace storages::mongo
92+
93+
USERVER_NAMESPACE_END

mongo/src/formats/bson/document.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <formats/bson/value_impl.hpp>
44
#include <userver/formats/bson/inline.hpp>
5+
#include <userver/formats/bson/serialize.hpp>
56
#include <userver/utils/assert.hpp>
67

78
USERVER_NAMESPACE_BEGIN
@@ -20,6 +21,11 @@ Document::Document(impl::BsonHolder bson)
2021
: Value(std::make_shared<impl::ValueImpl>(std::move(bson)))
2122
{}
2223

24+
void PrintTo(const Document& value, std::ostream* os)
25+
{
26+
*os << ToCanonicalJsonString(value);
27+
}
28+
2329
} // namespace formats::bson
2430

2531
USERVER_NAMESPACE_END

mongo/src/formats/bson/value.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <userver/formats/bson/bson_builder.hpp>
1010
#include <userver/formats/bson/document.hpp>
1111
#include <userver/formats/bson/serialize.hpp>
12+
#include <userver/formats/json/value.hpp>
1213
#include <userver/utils/algo.hpp>
1314

1415
USERVER_NAMESPACE_BEGIN

0 commit comments

Comments
 (0)