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