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// clang-format off
22
23/// @ingroup userver_components userver_base_classes
24///
25/// @brief Base class for YDB-based distlock worker components
26///
27/// A component that implements a distlock with lock in YDB. Inherit from
28/// DistLockComponentBase and implement DoWork(). Lock options are configured
29/// in static config.
30///
31/// The class must be used for infinite loop jobs.
32///
33/// ## Static configuration example:
34///
35/// @snippet ydb/functional_tests/basic/static_config.yaml sample-dist-lock
36///
37/// ## Static options:
38/// name | Description | Default value
39/// -------------- | ------------ | -------------
40/// semaphore-name | name of the semaphore within the coordination node | --
41/// database-settings.dbname | the key of the database within ydb component (NOT the actual database path) | --
42/// database-settings.coordination-node | name of the coordination node within the database | --
43/// initial-setup | if true, then create the coordination node and the semaphore unless they already exist | true
44/// task-processor | the name of the TaskProcessor for running DoWork | main-task-processor
45/// node-settings.session-grace-period | the time after which the lock will be given to another host after a network failure | 10s
46/// session-timeout | for how long we will try to restore session after a network failure before dropping it | 5s
47/// restart-session-delay | backoff before attempting to reconnect session after it returns "permanent failure" | 1s
48/// acquire-interval | backoff before repeating a failed Acquire call | 100ms
49/// restart-delay | backoff before calling DoWork again after it returns or throws | 100ms
50/// cancel-task-time-limit | time, within which a cancelled DoWork is expected to finish | 5s
51///
52/// @see @ref scripts/docs/en/userver/periodics.md
53
54// clang-format on
56public:
57 DistLockComponentBase(const components::ComponentConfig&, const components::ComponentContext&);
58 ~DistLockComponentBase() override;
59
60 /// @brief Checks if the the current service instance owns the lock.
61 ///
62 /// Useful for:
63 ///
64 /// 1. Writing metrics only on the primary (for the given distlock) host.
65 ///
66 /// 2. Running on-demand work, e.g. in handlers, only on the primary host.
67 /// The work must be short-lived (single requests with small timeout),
68 /// otherwise brain split
69 /// (where multiple hosts consider themselves primary) is possible.
70 bool OwnsLock() const noexcept;
71
72 static yaml_config::Schema GetStaticConfigSchema();
73
74protected:
75 /// Override this function with anything that must be done under the lock.
76 ///
77 /// @note `DoWork` must honour task cancellation and stop ASAP when
78 /// it is cancelled, otherwise brain split is possible (IOW, two different
79 /// users do work assuming both of them hold the lock, which is not true).
80 ///
81 /// @note When DoWork exits for any reason, the lock is dropped, then after
82 /// `restart-delay` the lock is attempted to be re-acquired (but by that time
83 /// another host likely acquires the lock).
84 ///
85 /// ## Example implementation
86 ///
87 /// @snippet ydb/functional_tests/basic/ydb_service.cpp DoWork
88 virtual void DoWork() = 0;
89
90 /// Override this function to provide a custom testsuite handler, e.g. one
91 /// that does not contain a "while not cancelled" loop.
92 /// Calls `DoWork` by default.
93 ///
94 /// In testsuite runs, the normal DoWork execution disabled by default.
95 /// There is an API to call DoWorkTestsuite from testsuite, imitating waiting
96 /// until DoWork runs:
97 ///
98 /// @snippet ydb/functional_tests/basic/tests/test_distlock.py run
99 virtual void DoWorkTestsuite() { DoWork(); }
100
101 /// Must be called at the end of the constructor of the derived component.
102 void Start();
103
104 /// Must be called in the destructor of the derived component.
105 void Stop() noexcept;
106
107private:
108 testsuite::TestsuiteTasks& testsuite_tasks_;
109 const std::string testsuite_task_name_;
110
111 // Worker contains a task that may refer to other fields, so it must be right
112 // before subscriptions. Add new fields above this comment.
113 std::optional<DistLockedWorker> worker_;
114
115 // Subscriptions must be the last fields.
116 utils::statistics::Entry statistics_holder_;
117};
118
119} // namespace ydb
120
121USERVER_NAMESPACE_END