userver: userver/dist_lock/dist_locked_worker.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
dist_locked_worker.hpp
1#pragma once
2
3#include <chrono>
4#include <functional>
5#include <memory>
6#include <optional>
7#include <string>
8
9#include <userver/dist_lock/dist_lock_settings.hpp>
10#include <userver/dist_lock/dist_lock_strategy.hpp>
11#include <userver/dist_lock/statistics.hpp>
12#include <userver/engine/mutex.hpp>
13#include <userver/engine/task/task_with_result.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace dist_lock {
18namespace impl {
19
20class Locker;
21
22} // namespace impl
23
24/// A high-level primitive that perpetually tries to acquire a distributed lock
25/// and runs user callback in a separate task while the lock is held.
26/// Cancels the task when the lock is lost.
27class DistLockedWorker final {
28 public:
29 using WorkerFunc = std::function<void()>;
30
31 /// Creates a DistLockedWorker.
32 /// @param name name of the worker
33 /// @param worker_func a callback that's started each time we acquire the lock
34 /// and is cancelled when the lock is lost.
35 /// @param settings distributed lock settings
36 /// @param strategy distributed locking strategy
37 /// @param task_processor TaskProcessor for running `worker_func`,
38 /// using current TaskProcessor if `nullptr`
39 /// @note `worker_func` must honour task cancellation and stop ASAP when
40 /// it is cancelled, otherwise brain split is possible (IOW, two different
41 /// users do work assuming both of them hold the lock, which is not true).
42 DistLockedWorker(std::string name, WorkerFunc worker_func,
43 std::shared_ptr<DistLockStrategyBase> strategy,
44 const DistLockSettings& settings = {},
45 engine::TaskProcessor* task_processor = nullptr);
46
47 ~DistLockedWorker();
48
49 /// Name of the worker.
50 const std::string& Name() const;
51
52 /// Retrieves settings in a thread-safe way.
54
55 /// Update settings in a thread-safe way.
57
58 /// Starts acquiring the lock. Please note that it's possible that the lock is
59 /// acquired and the WorkerFunc is entered *before* Start() returns.
60 /// @see DistLockedTask::DistLockedTask
61 void Start();
62
63 /// Stops acquiring the lock. It is guaranteed that the lock is not held after
64 /// Stop() return and WorkerFunc is stopped (if was started).
65 void Stop();
66
67 /// Run task once acquiring the lock.
68 /// @throws std::exception rethrows exception from `worker_func`.
69 void RunOnce();
70
71 /// @returns whether the DistLockedTask is started.
72 bool IsRunning() const;
73
74 /// Returns for how long the lock is held (if held at all). Returned value
75 /// may be less than the real duration.
76 std::optional<std::chrono::steady_clock::duration> GetLockedDuration() const;
77
78 /// Returns lock acquisition statistics.
79 const Statistics& GetStatistics() const;
80
81 private:
82 engine::TaskProcessor& GetTaskProcessor() const noexcept;
83
84 std::shared_ptr<impl::Locker> locker_ptr_;
85
86 mutable engine::Mutex locker_task_mutex_;
87 engine::TaskWithResult<void> locker_task_;
88
89 engine::TaskProcessor* const task_processor_;
90};
91
92void DumpMetric(utils::statistics::Writer& writer,
93 const DistLockedWorker& worker);
94
95} // namespace dist_lock
96
97USERVER_NAMESPACE_END