userver: userver/dist_lock/dist_locked_worker.hpp Source File
Loading...
Searching...
No Matches
dist_locked_worker.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/dist_lock/dist_locked_worker.hpp
4/// @brief @copybrief dist_lock::DistLockedWorker
5
6#include <chrono>
7#include <functional>
8#include <memory>
9#include <optional>
10#include <string>
11
12#include <userver/dist_lock/dist_lock_settings.hpp>
13#include <userver/dist_lock/dist_lock_strategy.hpp>
14#include <userver/dist_lock/statistics.hpp>
15#include <userver/engine/mutex.hpp>
16#include <userver/engine/task/task_with_result.hpp>
17#include <userver/logging/level.hpp>
18
19USERVER_NAMESPACE_BEGIN
20
21namespace dist_lock {
22namespace impl {
23
24class Locker;
25
26} // namespace impl
27
28/// @brief Perpetually acquires a distributed lock and runs a callback while it is held
29/// and runs user callback in a separate task while the lock is held.
30/// Cancels the task when the lock is lost.
31class DistLockedWorker final {
32public:
33 using WorkerFunc = std::function<void()>;
34
35 /// Creates a DistLockedWorker.
36 /// @param name name of the worker
37 /// @param worker_func a callback that's started each time we acquire the lock
38 /// and is cancelled when the lock is lost.
39 /// @param settings distributed lock settings
40 /// @param strategy distributed locking strategy
41 /// @param task_processor TaskProcessor for running `worker_func`,
42 /// using current TaskProcessor if `nullptr`
43 /// @param locker_log_level Log level for Locker (default is info)
44 /// @note `worker_func` must honour task cancellation and stop ASAP when
45 /// it is cancelled, otherwise brain split is possible (IOW, two different
46 /// users do work assuming both of them hold the lock, which is not true).
48 std::string name,
49 WorkerFunc worker_func,
50 std::shared_ptr<DistLockStrategyBase> strategy,
51 const DistLockSettings& settings = {},
52 engine::TaskProcessor* task_processor = nullptr,
53 logging::Level locker_log_level = logging::Level::kInfo
54 );
55
56 ~DistLockedWorker();
57
58 /// Name of the worker.
59 const std::string& Name() const;
60
61 /// Retrieves settings in a thread-safe way.
63
64 /// Update settings in a thread-safe way.
66
67 /// Starts acquiring the lock. Please note that it's possible that the lock is
68 /// acquired and the WorkerFunc is entered *before* Start() returns.
69 /// @see DistLockedTask::DistLockedTask
70 void Start();
71
72 /// Stops acquiring the lock. It is guaranteed that the lock is not held after
73 /// Stop() return and WorkerFunc is stopped (if was started).
74 void Stop();
75
76 /// Run task once acquiring the lock.
77 /// @throws std::exception rethrows exception from `worker_func`.
78 void RunOnce();
79
80 /// @returns whether the DistLockedTask is started.
81 bool IsRunning() const;
82
83 /// @returns is current worker owns the lock
84 bool OwnsLock() const noexcept;
85
86 /// Returns for how long the lock is held (if held at all). Returned value
87 /// may be less than the real duration.
88 std::optional<std::chrono::steady_clock::duration> GetLockedDuration() const;
89
90 /// Returns lock acquisition statistics.
91 const Statistics& GetStatistics() const;
92
93 /// Returns `true` when it is advised to cancel the task.
94 bool IsCancelAdvised() const;
95
96private:
97 engine::TaskProcessor& GetTaskProcessor() const noexcept;
98
99 std::shared_ptr<impl::Locker> locker_ptr_;
100
101 mutable engine::Mutex locker_task_mutex_;
102 engine::TaskWithResult<void> locker_task_;
103
104 engine::TaskProcessor* const task_processor_;
105};
106
107void DumpMetric(utils::statistics::Writer& writer, const DistLockedWorker& worker);
108
109} // namespace dist_lock
110
111USERVER_NAMESPACE_END