userver: userver/utils/trx_tracker.hpp Source File
Loading...
Searching...
No Matches
trx_tracker.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/trx_tracker.hpp
4/// @brief Tracking for heavy operations while having active transactions.
5
6#include <optional>
7#include <thread>
8
9#include <userver/utils/impl/source_location.hpp>
10#include <userver/utils/statistics/rate.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14/// @brief Tracking for heavy operations while having active transactions.
15///
16/// Some operations, like HTTP requests, are heavy and can take too long during an incident. If they are called during
17/// an active database transaction, connection will be held for longer and connection pool will be exhausted.
18/// Transaction tracker prevents this by holding counter of active transactions in TaskLocalVariable
19/// and checking for active transactions in heavy operations.
20///
21/// ## Example usage:
22///
23/// @snippet utils/trx_tracker_test.cpp Sample TransactionTracker usage
24///
25/// @see @ref scripts/docs/en/userver/long_transactions.md
26namespace utils::trx_tracker {
27
28namespace impl {
29
30/// @brief Global enabler for transaction tracker.
31class GlobalEnabler final {
32public:
33 explicit GlobalEnabler(bool enable = true);
34 ~GlobalEnabler();
35
36 GlobalEnabler(const GlobalEnabler&) = delete;
37 GlobalEnabler& operator=(const GlobalEnabler&) = delete;
38};
39
40/// @brief Check if transaction tracker is enabled.
41bool IsEnabled() noexcept;
42
43/// @brief Unique ID for every task.
44///
45/// Sometimes transactions start and end in different coroutines. To prevent transaction from incrementing and
46/// decrementing different transaction counters, TransactionLock stores TaskId on Lock and
47/// checks that stored TaskId is the same as current TaskId in Unlock.
48class TaskId final {
49public:
50 TaskId();
51
52 bool operator==(const TaskId& other) const;
53 bool operator!=(const TaskId& other) const;
54
55private:
56 std::thread::id created_thread_id_;
57 std::uint64_t thread_local_counter_;
58};
59
60} // namespace impl
61
62/// @brief Class for incrementing and decrementing transaction counter.
63class TransactionLock final {
64public:
65 TransactionLock() = default;
66 TransactionLock(const TransactionLock&) = delete;
67 TransactionLock(TransactionLock&&) noexcept;
68 TransactionLock operator=(const TransactionLock&) = delete;
69 TransactionLock& operator=(TransactionLock&&) noexcept;
70
71 /// @brief Decrement transaction counter on destruction.
73
74 /// @brief Manually increment transaction counter.
75 void Lock() noexcept;
76
77 /// @brief Manually decrement transaction counter.
78 void Unlock() noexcept;
79
80private:
81 std::optional<impl::TaskId> task_id_;
82};
83
84/// @brief Check for active transactions.
85void CheckNoTransactions(utils::impl::SourceLocation location = utils::impl::SourceLocation::Current());
86
87/// @overload
88void CheckNoTransactions(std::string_view location);
89
90/// @brief Disable check for active transactions.
91///
92/// To consciously call a heavy operation in active transaction, check can be disabled by creating an instance of this
93/// class. Checks will be disabled until every instance either has Reenable() method called or is destroyed.
94///
95/// @snippet utils/trx_tracker_test.cpp Sample CheckDisabler usage
96class CheckDisabler final {
97public:
98 /// @brief Disable check for active transactions.
99 explicit CheckDisabler();
100
101 /// @brief Reenable check for active transactions on destruction.
103
104 CheckDisabler(const CheckDisabler&) = delete;
105 CheckDisabler(CheckDisabler&&) = delete;
106 CheckDisabler operator=(const CheckDisabler&) = delete;
107 CheckDisabler operator=(CheckDisabler&&) = delete;
108
109 /// @brief Manually reenable check for active transactions.
110 void Reenable() noexcept;
111
112private:
113 bool reenabled_ = false;
114};
115
116/// @brief Statistics for transaction tracker.
117struct TransactionTrackerStatistics final {
118 /// @brief How many times check for active transactions was triggered.
119 utils::statistics::Rate triggers{0};
120};
121
122/// @brief Get statistics for transaction tracker.
123TransactionTrackerStatistics GetStatistics() noexcept;
124
125/// @brief Reset statistics for transaction tracker.
127
128} // namespace utils::trx_tracker
129
130USERVER_NAMESPACE_END