userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
snapshot.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/dynamic_config/snapshot.hpp
4
/// @brief @copybrief dynamic_config::Snapshot
5
6
#
include
<
any
>
7
#
include
<
cstddef
>
8
#
include
<
cstdint
>
9
#
include
<
string
>
10
#
include
<
string_view
>
11
#
include
<
type_traits
>
12
#
include
<
utility
>
13
#
include
<
vector
>
14
15
#
include
<
userver
/
compiler
/
impl
/
lifetime
.
hpp
>
16
#
include
<
userver
/
dynamic_config
/
impl
/
snapshot
.
hpp
>
17
#
include
<
userver
/
dynamic_config
/
impl
/
to_json
.
hpp
>
18
#
include
<
userver
/
dynamic_config
/
registered_config_meta
.
hpp
>
19
#
include
<
userver
/
formats
/
json_fwd
.
hpp
>
20
#
include
<
userver
/
utils
/
fast_pimpl
.
hpp
>
21
22
USERVER_NAMESPACE_BEGIN
23
24
namespace
dynamic_config {
25
26
/// Opaque schema hash supplied by code generation. userver does not calculate it.
27
struct
SchemaHash
final
{
28
constexpr
SchemaHash() =
default
;
29
30
constexpr
explicit
SchemaHash(std::string_view value)
31
: value(value)
32
{}
33
34
std::string_view value;
35
};
36
37
/// A strong typedef for usage in dynamic_config::Key constructors.
38
struct
DefaultAsJsonString
final
{
39
constexpr
explicit
DefaultAsJsonString(std::string_view json_string);
40
41
std::string_view json_string;
42
};
43
44
/// A config name-value pair for usage in dynamic_config::Key constructors.
45
struct
ConfigDefault
final
{
46
template
<
typename
T>
47
ConfigDefault(std::string_view name,
const
T& value);
48
49
ConfigDefault(std::string_view name, DefaultAsJsonString default_json);
50
/// @warning The schema hash must be supplied by code generation. userver
51
/// treats it as an opaque value and does not calculate it.
52
ConfigDefault
(std::string_view name, DefaultAsJsonString default_json, SchemaHash schema_hash);
53
54
std::string_view name;
55
std::string default_json;
56
std::string schema_hash;
57
};
58
59
/// A tag type for usage in dynamic_config::Key constructors.
60
struct
ConstantConfig
final
{
61
constexpr
explicit
ConstantConfig() =
default
;
62
};
63
64
/// @brief A config key is a unique identifier for a config variable
65
/// @snippet core/src/dynamic_config/config_test.cpp key bool
66
template
<
typename
Variable>
67
class
Key
final
{
68
public
:
69
/// The type of the parsed config variable.
70
using
VariableType
= Variable;
71
72
using
JsonParser = Variable (*)(
const
formats::
json
::
Value
&);
73
using
DocsMapParser = Variable (*)(
const
DocsMap&);
74
75
/// @brief The constructor for a trivial `VariableType`, e.g. `bool`, integer,
76
/// `double`, `string`. The default is passed by value.
77
///
78
/// Usage example:
79
/// @snippet core/src/dynamic_config/config_test.cpp key bool
80
Key
(std::string_view name,
const
VariableType
& default_value);
81
82
/// @brief The constructor for a trivial `VariableType` with schema
83
/// metadata.
84
/// @param schema_hash Opaque schema hash.
85
/// @warning The schema hash must be supplied by code generation. userver
86
/// treats it as an opaque value and does not calculate it.
87
Key
(std::string_view name,
const
VariableType
& default_value, SchemaHash schema_hash);
88
89
/// @brief The constructor for a non-trivial `VariableType`. The default is
90
/// passed as a JSON string.
91
///
92
/// Uses formats::json::Value `Parse` customization point function to parse
93
/// `VariableType`.
94
///
95
/// Usage example:
96
/// @snippet core/src/dynamic_config/config_test.cpp struct config cpp
97
Key
(std::string_view name, DefaultAsJsonString default_json);
98
99
/// @brief The constructor for a non-trivial `VariableType` with schema
100
/// metadata.
101
/// @param schema_hash Opaque schema hash.
102
/// @warning The schema hash must be supplied by code generation. userver
103
/// treats it as an opaque value and does not calculate it.
104
Key
(std::string_view name, DefaultAsJsonString default_json, SchemaHash schema_hash);
105
106
/// @brief The constructor that provides a special parser from JSON.
107
/// @warning Prefer the constructors above whenever possible.
108
/// @details Can be used when generic `Parse` is not applicable. Sometimes
109
/// used to add validation, e.g. minimum, maximum, string pattern, etc.
110
Key
(std::string_view name, JsonParser parser, DefaultAsJsonString default_json);
111
112
/// @brief The constructor with a custom JSON parser and schema metadata.
113
/// @param name config variable name
114
/// @param parser custom JSON parser for the variable
115
/// @param default_json default value as a JSON string
116
/// @param schema_hash Opaque schema hash.
117
/// Stored in the global registry and retrievable via
118
/// dynamic_config::impl::GetRegisteredConfigsMeta() as
119
/// dynamic_config::RegisteredConfigMeta::schema_hash.
120
/// @warning The schema hash must be supplied by code generation. userver
121
/// treats it as an opaque value and does not calculate it.
122
Key
(std::string_view name, JsonParser parser, DefaultAsJsonString default_json, SchemaHash schema_hash);
123
124
/// @brief The constructor that parses multiple JSON config items
125
/// into a single C++ object.
126
///
127
/// To register schema metadata for the JSON config items, pass the generated
128
/// `variable_namespace::GetSchemaHash()` to each ConfigDefault.
129
/// @warning Prefer to use a separate `Key` per JSON config item and use the
130
/// constructors above whenever possible.
131
template
<std::size_t N>
132
Key
(DocsMapParser parser,
const
ConfigDefault (&default_json_map)[N]);
133
134
/// Creates a config that always has the same value.
135
Key
(ConstantConfig,
VariableType
value);
136
137
/// @cond
138
Key(impl::InternalTag, std::string_view name);
139
140
Key(impl::InternalTag, DocsMapParser parser);
141
/// @endcond
142
143
Key(
const
Key
&)
noexcept
=
delete
;
144
Key
& operator=(
const
Key
&)
noexcept
=
delete
;
145
146
/// @returns the name of the single registered config item, or the explicit
147
/// name of an internal derived key. Calling this for a key with zero or
148
/// multiple config items and no explicit internal name is an invariant violation.
149
std::string_view
GetName
()
const
noexcept
;
150
151
/// Parses the config. Useful only in some very niche scenarios. The config
152
/// value should be typically be retrieved from dynamic_config::Snapshot,
153
/// which is obtained from components::DynamicConfig in production or from
154
/// dynamic_config::StorageMock in unit tests.
155
VariableType
Parse
(
const
DocsMap& docs_map)
const
;
156
157
private
:
158
friend
struct
impl::ConfigIdGetter;
159
160
const
impl::ConfigId id_;
161
};
162
163
/// @brief The shared snapshot of
164
/// @ref scripts/docs/en/userver/dynamic_config.md "dynamic configs". Cheap to
165
/// copy, even cheaper to move. Thread safe, not updated with new dynamic
166
/// config values in background (it's a snapshot!).
167
///
168
/// When a config update comes in via new `DocsMap`, configs of all
169
/// the registered types are constructed and stored in `Config`. After that
170
/// the `DocsMap` is dropped.
171
///
172
/// Config types are automatically registered if they are used
173
/// somewhere in the program.
174
///
175
/// ## Usage example:
176
/// @snippet core/src/components/component_sample_test.cpp Sample user component runtime config source
177
class
Snapshot
final
{
178
public
:
179
Snapshot(
const
Snapshot&);
180
Snapshot& operator=(
const
Snapshot&);
181
182
Snapshot(Snapshot&&)
noexcept
;
183
Snapshot& operator=(Snapshot&&)
noexcept
;
184
185
~Snapshot();
186
187
/// Used to access individual configs in the type-safe config map
188
template
<
typename
VariableType>
189
const
VariableType&
operator
[](
const
Key
<VariableType>& key)
const
& USERVER_IMPL_LIFETIME_BOUND;
190
191
/// Used to access individual configs in the type-safe config map
192
template
<
typename
VariableType>
193
const
VariableType&
operator
[](
const
Key
<VariableType>&) &&;
194
195
private
:
196
// for the constructor
197
friend
class
Source;
198
friend
class
impl::StorageData;
199
friend
struct
Diff;
200
201
explicit
Snapshot(
const
impl::StorageData& storage);
202
203
const
impl::SnapshotData& GetData()
const
;
204
205
struct
Impl;
206
utils
::FastPimpl<Impl, 16, 8> impl_;
207
};
208
209
// ========================== Implementation follows ==========================
210
211
constexpr
DefaultAsJsonString::DefaultAsJsonString(std::string_view json_string)
212
: json_string(json_string)
213
{}
214
215
template
<
typename
T>
216
ConfigDefault::ConfigDefault(std::string_view name,
const
T& value)
217
: name(name),
218
default_json(impl::ToJsonString(value))
219
{}
220
221
template
<
typename
Variable>
222
Key
<Variable>::
Key
(std::string_view name,
const
VariableType
& default_value)
223
:
Key
(name, default_value, SchemaHash{})
224
{}
225
226
template
<
typename
Variable>
227
Key
<Variable>::
Key
(std::string_view name,
const
VariableType
& default_value, SchemaHash schema_hash)
228
: id_(impl::Register(
229
[name = std::string{name}](
const
auto
& docs_map) -> std::any {
230
return
impl::DocsMapGet(docs_map, name).
template
As<
VariableType
>();
231
},
232
{{.name = std::string{name},
233
.schema_hash = std::string{schema_hash.value},
234
.default_as_json_string = impl::ToJsonString(default_value)}}
235
))
236
{}
237
238
template
<
typename
Variable>
239
Key
<Variable>::
Key
(std::string_view name, DefaultAsJsonString default_json)
240
:
Key
(name, default_json, SchemaHash{})
241
{}
242
243
template
<
typename
Variable>
244
Key
<Variable>::
Key
(std::string_view name, DefaultAsJsonString default_json, SchemaHash schema_hash)
245
: id_(impl::Register(
246
[name = std::string{name}](
const
auto
& docs_map) -> std::any {
247
return
impl::DocsMapGet(docs_map, name).
template
As<
VariableType
>();
248
},
249
{{.name = std::string{name},
250
.schema_hash = std::string{schema_hash.value},
251
.default_as_json_string = std::string{default_json.json_string}}}
252
))
253
{}
254
255
template
<
typename
Variable>
256
Key
<Variable>::
Key
(std::string_view name, JsonParser parser, DefaultAsJsonString default_json)
257
:
Key
(name, parser, default_json, SchemaHash{})
258
{}
259
260
template
<
typename
Variable>
261
Key
<Variable>::
Key
(std::string_view name, JsonParser parser, DefaultAsJsonString default_json, SchemaHash schema_hash)
262
: id_(impl::Register(
263
[name = std::string{name}, parser](
const
auto
& docs_map) -> std::any {
264
return
parser(impl::DocsMapGet(docs_map, name));
265
},
266
{{.name = std::string{name},
267
.schema_hash = std::string{schema_hash.value},
268
.default_as_json_string = std::string{default_json.json_string}}}
269
))
270
{}
271
272
template
<
typename
Variable>
273
template
<std::size_t N>
274
Key
<Variable>::
Key
(DocsMapParser parser,
const
ConfigDefault (&default_json_map)[N])
275
: id_([parser, &default_json_map] {
276
std::vector<impl::ConfigMetadata> config_metadata;
277
config_metadata.reserve(N);
278
for
(
const
auto
& config_default : default_json_map) {
279
config_metadata.push_back({
280
.name = std::string{config_default.name},
281
.schema_hash = config_default.schema_hash,
282
.default_as_json_string = config_default.default_json,
283
});
284
}
285
return
impl::Register(
286
[parser](
const
DocsMap& docs_map) -> std::any {
return
parser(docs_map); },
287
std::move(config_metadata)
288
);
289
}())
290
{}
291
292
template
<
typename
Variable>
293
Key
<Variable>::
Key
(ConstantConfig
/*tag*/
,
VariableType
value)
294
: id_(impl::Register([value = std::move(value)](
const
DocsMap&
/*unused*/
) {
return
value; }, {}))
295
{}
296
297
template
<
typename
Variable>
298
Key
<Variable>::Key(impl::InternalTag, std::string_view name)
299
: id_(impl::RegisterInternal(
300
std::string{name},
301
[name = std::string{name}](
const
auto
& docs_map) -> std::any {
302
return
impl::DocsMapGet(docs_map, name).
template
As<
VariableType
>();
303
}
304
))
305
{}
306
307
template
<
typename
Variable>
308
Key
<Variable>::Key(impl::InternalTag, DocsMapParser parser)
309
: id_(impl::RegisterInternal(
310
std::string{},
311
[parser](
const
DocsMap& docs_map) -> std::any {
return
parser(docs_map); }
312
))
313
{}
314
315
template
<
typename
VariableType>
316
std::string_view
Key
<VariableType>::
GetName
()
const
noexcept
{
317
return
impl::GetName(id_);
318
}
319
320
template
<
typename
VariableType>
321
VariableType
Key
<VariableType>::
Parse
(
const
DocsMap& docs_map)
const
{
322
return
std::any_cast<
VariableType
>(impl::MakeConfig(id_, docs_map));
323
}
324
325
template
<
typename
VariableType>
326
const
VariableType&
Snapshot
::
operator
[](
const
Key
<VariableType>& key)
const
& USERVER_IMPL_LIFETIME_BOUND {
327
return
GetData().Get<VariableType>(impl::ConfigIdGetter::Get(key));
328
}
329
330
template
<
typename
VariableType>
331
const
VariableType& Snapshot::
operator
[](
const
Key
<VariableType>&) && {
332
static_assert
(!
sizeof
(VariableType),
"keep the Snapshot before using, please"
);
333
}
334
335
}
// namespace dynamic_config
336
337
USERVER_NAMESPACE_END
userver
dynamic_config
snapshot.hpp
Generated on
for userver by
Doxygen
1.17.0