userver: userver/ydb/dist_lock/component_base.hpp Source File
Loading...
Searching...
No Matches
component_base.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/ydb/dist_lock/component_base.hpp
4/// @brief @copybrief ydb::DistLockComponentBase
5
6#include <optional>
7#include <string>
8
9#include <userver/components/component_base.hpp>
10#include <userver/ydb/dist_lock/worker.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace testsuite {
15class TestsuiteTasks;
16} // namespace testsuite
17
18namespace ydb {
19
20/// @ingroup userver_components userver_base_classes
21///
22/// @brief Base class for YDB-based distlock worker components
23///
24/// A component that implements a distlock with lock in YDB. Inherit from
25/// DistLockComponentBase and implement DoWork(). Lock options are configured
26/// in static config.
27///
28/// The class must be used for infinite loop jobs.
29///
30/// ## Static configuration example:
31///
32/// @snippet ydb/functional_tests/basic/static_config.yaml sample-dist-lock
33///
34/// ## Static options of ydb::DistLockComponentBase :
35/// @include{doc} scripts/docs/en/components_schema/ydb/src/ydb/dist_lock/component_base.md
36///
37/// Options inherited from @ref components::ComponentBase :
38/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
39///
40/// @see @ref scripts/docs/en/userver/periodics.md
41class DistLockComponentBase : public components::ComponentBase {
42public:
43 DistLockComponentBase(const components::ComponentConfig&, const components::ComponentContext&);
44
45 /// @brief Checks if the the current service instance owns the lock.
46 ///
47 /// Useful for:
48 ///
49 /// 1. Writing metrics only on the primary (for the given distlock) host.
50 ///
51 /// 2. Running on-demand work, e.g. in handlers, only on the primary host.
52 /// The work must be short-lived (single requests with small timeout),
53 /// otherwise brain split
54 /// (where multiple hosts consider themselves primary) is possible.
55 bool OwnsLock() const noexcept;
56
57 static yaml_config::Schema GetStaticConfigSchema();
58
59protected:
60 /// Override this function with anything that must be done under the lock.
61 ///
62 /// @note `DoWork` must honour task cancellation and stop ASAP when
63 /// it is cancelled, otherwise brain split is possible (IOW, two different
64 /// users do work assuming both of them hold the lock, which is not true).
65 ///
66 /// @note When DoWork exits for any reason, the lock is dropped, then after
67 /// `restart-delay` the lock is attempted to be re-acquired (but by that time
68 /// another host likely acquires the lock).
69 ///
70 /// ## Example implementation
71 ///
72 /// @snippet ydb/functional_tests/basic/ydb_service.cpp DoWork
73 virtual void DoWork() = 0;
74
75 /// Override this function to provide a custom testsuite handler, e.g. one
76 /// that does not contain a "while not cancelled" loop.
77 /// Calls `DoWork` by default.
78 ///
79 /// In testsuite runs, the normal DoWork execution disabled by default.
80 /// There is an API to call DoWorkTestsuite from testsuite, imitating waiting
81 /// until DoWork runs:
82 ///
83 /// @snippet ydb/functional_tests/basic/tests/test_distlock.py run
84 virtual void DoWorkTestsuite() { DoWork(); }
85
86 /// Must be called at the end of the constructor of the derived component.
87 void Start();
88
89 /// Must be called in the destructor of the derived component.
90 void Stop() noexcept;
91
92private:
93 testsuite::TestsuiteTasks& testsuite_tasks_;
94 const std::string testsuite_task_name_;
95
96 // Worker contains a task that may refer to other fields, so it must be right
97 // before subscriptions. Add new fields above this comment.
98 std::optional<DistLockedWorker> worker_;
99};
100
101} // namespace ydb
102
103USERVER_NAMESPACE_END