userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
dist_lock_component_base.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/storages/postgres/dist_lock_component_base.hpp
4
/// @brief @copybrief storages::postgres::DistLockComponentBase
5
6
#
include
<
userver
/
components
/
component_base
.
hpp
>
7
#
include
<
userver
/
dist_lock
/
dist_locked_worker
.
hpp
>
8
#
include
<
userver
/
dynamic_config
/
snapshot
.
hpp
>
9
#
include
<
userver
/
dynamic_config
/
source
.
hpp
>
10
#
include
<
userver
/
storages
/
postgres
/
dist_lock_strategy
.
hpp
>
11
12
USERVER_NAMESPACE_BEGIN
13
14
namespace
storages::
postgres
{
15
16
/// @ingroup userver_components userver_base_classes
17
///
18
/// @brief Base class for postgres-based distlock worker components
19
///
20
/// A component that implements a distlock with lock in Postgres. Inherit from
21
/// DistLockComponentBase and implement DoWork(). Lock options are configured
22
/// in static config. To customize a distlock for testsuite override DoWorkTestsuite().
23
///
24
/// By default the distlock is started and stopped automatically by the framework
25
/// in all environments except testsuite. If manual control over the distlock startup
26
/// and shutdown is needed pass DisableAutostartAtBase{} to the DistLockComponentBase .ctor.
27
///
28
/// The class must be used for infinite loop jobs. If you want a distributed
29
/// periodic, you should look at locked_periodiccomponents::PgLockedPeriodic.
30
///
31
/// @see dist_lock::DistLockedTask
32
/// @see locked_periodiccomponents::PgLockedPeriodic
33
///
34
/// ## Static configuration example:
35
///
36
/// ```yaml
37
/// example-distlock:
38
/// cluster: postgresql-service
39
/// table: service.distlocks
40
/// lockname: master
41
/// pg-timeout: 1s
42
/// lock-ttl: 10s
43
/// autostart: true
44
/// ```
45
/// See config `POSTGRES_DISTLOCK_SETTINGS`, some of parameters can be dynamically overridden.
46
///
47
/// ## Static options of storages::postgres::DistLockComponentBase :
48
/// @include{doc} scripts/docs/en/components_schema/postgresql/src/storages/postgres/dist_lock_component_base.md
49
///
50
/// Options inherited from @ref components::ComponentBase :
51
/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
52
///
53
/// ## Migration example
54
///
55
/// You have to create a SQL table for distlocks. An example of the migration
56
/// script is as following:
57
///
58
/// ```SQL
59
/// CREATE TABLE service.distlocks
60
/// (
61
/// key TEXT PRIMARY KEY,
62
/// owner TEXT,
63
/// expiration_time TIMESTAMPTZ
64
/// );
65
/// ```
66
///
67
/// @see @ref scripts/docs/en/userver/periodics.md
68
class
DistLockComponentBase
:
public
components
::
ComponentBase
{
69
public
:
70
struct
DisableAutostartAtBase
{};
71
72
/// @brief Constructs the distlock base and enables automatic startup and shutdown of the distlock.
73
DistLockComponentBase
(
74
const
components
::ComponentConfig& component_config,
75
const
components
::ComponentContext& component_context
76
);
77
78
/// @brief Constructs the distlock base and disables automatic startup and shutdown of the distlock.
79
/// The dislock should be started and stopped manually via AutostartDistlock() and StopDistLock() calls.
80
DistLockComponentBase
(
81
const
components
::ComponentConfig& component_config,
82
const
components
::ComponentContext& component_context,
83
DisableAutostartAtBase
84
);
85
86
~DistLockComponentBase() override;
87
88
dist_lock
::DistLockedWorker& GetWorker();
89
90
/// @note In testsuite always returns `true`, because there is only one host.
91
bool
OwnsLock
()
const
noexcept
;
92
93
static
yaml_config::Schema GetStaticConfigSchema();
94
95
protected
:
96
/// Override this function with anything that must be done under the pg lock.
97
///
98
/// ## Example implementation
99
///
100
/// ```cpp
101
/// void MyDistLockComponent::DoWork()
102
/// {
103
/// // `IsCancelAdvised` is advisory/soft signal to stop the task.
104
/// // Check it in every independent processing iteration.
105
/// // Whereas @ref engine::current_task::ShouldCancel() checks as frequently,
106
/// // as you can to honor low-level task cancellation.
107
/// while (!IsCancelAdvised())
108
/// {
109
/// // Start a new trace_id
110
/// auto span = tracing::Span::MakeRootSpan("my-dist-lock");
111
///
112
/// // If Foo() or other function in DoWork() throws an exception,
113
/// // DoWork() will be restarted in `restart-delay` seconds.
114
/// Foo();
115
///
116
/// // Check for cancellation after cpu-intensive Foo().
117
/// // You must check for cancellation at least every `lock-ttl`
118
/// // seconds to have time to notice lock prolongation failure.
119
/// if (engine::ShouldCancel()) break;
120
///
121
/// Bar();
122
/// }
123
/// }
124
/// ```
125
///
126
/// @note `DoWork` must honour task cancellation and stop ASAP when
127
/// it is cancelled, otherwise brain split is possible (IOW, two different
128
/// users do work assuming both of them hold the lock, which is not true).
129
virtual
void
DoWork
() = 0;
130
131
/// Override this function to provide custom testsuite handler.
132
virtual
void
DoWorkTestsuite
() {
DoWork
(
)
; }
133
134
/// Should be called in a .ctor of a derived class iff DisableAutostartAtBase{}
135
/// has been passed to the DistLockComponentBase .ctor.
136
void
AutostartDistLock
();
137
138
/// Should be called in a .dtor of a derived class iff DisableAutostartAtBase{}
139
/// has been passed to the DistLockComponentBase .ctor.
140
void
StopDistLock
();
141
142
/// Check this method when going for the next independent processing
143
/// iteration. Whereas @ref engine::current_task::ShouldCancel()
144
/// checks as frequently, as you can to honor low-level task cancellation.
145
bool
IsCancelAdvised
()
const
;
146
147
private
:
148
enum
class
AutostartDistlock :
bool
{ kNo =
false
, kYes =
true
};
149
150
DistLockComponentBase(
151
const
components
::ComponentConfig& component_config,
152
const
components
::ComponentContext& component_context,
153
AutostartDistlock enable_autostart_at_base
154
);
155
156
bool
ShouldRunOnHost(
const
dynamic_config::Snapshot& config)
const
;
157
void
OnConfigUpdate(
const
dynamic_config::Diff& diff);
158
159
dynamic_config::Source config_;
160
const
std::string name_;
161
const
std::string real_host_name_;
162
std::unique_ptr<
dist_lock
::DistLockedWorker> worker_;
163
bool
autostart_;
164
bool
testsuite_enabled_{
false
};
165
AutostartDistlock enable_autostart_at_base_;
166
dist_lock
::
DistLockSettings
default_settings_;
167
168
concurrent
::AsyncEventSubscriberScope subscription_token_;
169
};
170
171
}
// namespace storages::postgres
172
173
USERVER_NAMESPACE_END
userver
storages
postgres
dist_lock_component_base.hpp
Generated on
for userver by
Doxygen
1.17.0