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
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
17/// too long during an incident. If they are called during an active
18/// database transaction, connection will be held for longer and
19/// connection pool will be exhausted. Transaction tracker prevents this
20/// by holding counter of active transactions in TaskLocalVariable
21/// and checking for active transactions in heavy operations.
22///
23/// ## Example usage:
24///
25/// @snippet utils/trx_tracker_test.cpp Sample TransactionTracker usage
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.
46/// To prevent transaction from incrementing and decrementing different
47/// transaction counters, TransactionLock stores TaskId on Lock and
48/// checks that stored TaskId is the same as current TaskId in Unlock.
49class TaskId final {
50public:
51 TaskId();
52
53 bool operator==(const TaskId& other) const;
54 bool operator!=(const TaskId& other) const;
55
56private:
57 std::thread::id created_thread_id_;
58 std::uint64_t thread_local_counter_;
59};
60
61} // namespace impl
62
63/// @brief Class for incrementing and decrementing transaction counter.
64class TransactionLock final {
65public:
66 TransactionLock() = default;
67 TransactionLock(const TransactionLock&) = delete;
68 TransactionLock(TransactionLock&&) noexcept;
69 TransactionLock operator=(const TransactionLock&) = delete;
70 TransactionLock& operator=(TransactionLock&&) noexcept;
71
72 /// @brief Decrement transaction counter on destruction.
74
75 /// @brief Manually increment transaction counter.
76 void Lock() noexcept;
77
78 /// @brief Manually decrement transaction counter.
79 void Unlock() noexcept;
80
81private:
82 std::optional<impl::TaskId> task_id_;
83};
84
85/// @brief Check for active transactions.
86void CheckNoTransactions(utils::impl::SourceLocation location = utils::impl::SourceLocation::Current());
87
88/// @overload
89void CheckNoTransactions(std::string_view location);
90
91/// @brief Disable check for active transactions.
92///
93/// To consciously call a heavy operation in active transaction,
94/// check can be disabled by creating an instance of this class.
95/// Checks will be disabled until every instance either has
96/// Reenable() method called or is destroyed.
97class CheckDisabler final {
98public:
99 /// @brief Disable check for active transactions.
100 explicit CheckDisabler();
101
102 /// @brief Reenable check for active transactions on destruction.
104
105 CheckDisabler(const CheckDisabler&) = delete;
106 CheckDisabler(CheckDisabler&&) = delete;
107 CheckDisabler operator=(const CheckDisabler&) = delete;
108 CheckDisabler operator=(CheckDisabler&&) = delete;
109
110 /// @brief Manually reenable check for active transactions.
111 void Reenable() noexcept;
112
113private:
114 bool reenabled_ = false;
115};
116
117/// @brief Statistics for transaction tracker.
118struct TransactionTrackerStatistics final {
119 /// @brief How many times check for active transactions was triggered.
120 utils::statistics::Rate triggers{0};
121};
122
123/// @brief Get statistics for transaction tracker.
124TransactionTrackerStatistics GetStatistics() noexcept;
125
126/// @brief Reset statistics for transaction tracker.
128
129} // namespace utils::trx_tracker
130
131USERVER_NAMESPACE_END