22#include "rpc/common/APIVersion.hpp"
23#include "util/Assert.hpp"
24#include "util/newconfig/Array.hpp"
25#include "util/newconfig/ConfigConstraints.hpp"
26#include "util/newconfig/ConfigFileInterface.hpp"
27#include "util/newconfig/ConfigValue.hpp"
28#include "util/newconfig/Error.hpp"
29#include "util/newconfig/ObjectView.hpp"
30#include "util/newconfig/Types.hpp"
31#include "util/newconfig/ValueView.hpp"
37#include <initializer_list>
42#include <unordered_map>
47namespace util::config {
56 using KeyValuePair = std::pair<std::string_view, std::variant<ConfigValue, Array>>;
77 [[nodiscard]] std::optional<std::vector<Error>>
88 getObject(std::string_view prefix, std::optional<std::size_t> idx = std::nullopt)
const;
106 template <
typename T>
108 get(std::string_view fullKey)
const
110 ASSERT(map_.contains(fullKey),
"key {} does not exist in config", fullKey);
111 auto const val = map_.at(fullKey);
112 if (std::holds_alternative<ConfigValue>(val)) {
135 getArray(std::string_view prefix)
const;
144 contains(std::string_view key)
const;
161 [[nodiscard]]
Array const&
162 asArray(std::string_view key)
const;
170 [[nodiscard]] std::size_t
171 arraySize(std::string_view prefix)
const;
179 static std::chrono::milliseconds
189 template <
typename T>
226 getArrayIterator(std::string_view key)
const
228 auto const fullKey = addBracketsForArrayKey(key);
229 auto const it = std::ranges::find_if(map_, [&fullKey](
auto pair) {
return pair.first == fullKey; });
231 ASSERT(it != map_.end(),
"key {} does not exist in config", fullKey);
232 ASSERT(std::holds_alternative<Array>(it->second),
"Value of {} is not an array", fullKey);
243 [[nodiscard]]
static std::string
244 addBracketsForArrayKey(std::string_view key)
246 std::string fullKey = std::string(key);
247 if (!key.contains(
".[]"))
252 std::unordered_map<std::string_view, std::variant<ConfigValue, Array>> map_;
261static ClioConfigDefinition gClioConfig = ClioConfigDefinition{
262 {{
"database.type", ConfigValue{ConfigType::String}.defaultValue(
"cassandra").withConstraint(gValidateCassandraName)
264 {
"database.cassandra.contact_points", ConfigValue{ConfigType::String}.defaultValue(
"localhost")},
265 {
"database.cassandra.secure_connect_bundle", ConfigValue{ConfigType::String}.optional()},
266 {
"database.cassandra.port", ConfigValue{ConfigType::Integer}.withConstraint(gValidatePort).optional()},
267 {
"database.cassandra.keyspace", ConfigValue{ConfigType::String}.defaultValue(
"clio")},
268 {
"database.cassandra.replication_factor",
269 ConfigValue{ConfigType::Integer}.defaultValue(3u).withConstraint(gValidateUint16)},
270 {
"database.cassandra.table_prefix", ConfigValue{ConfigType::String}.optional()},
271 {
"database.cassandra.max_write_requests_outstanding",
272 ConfigValue{ConfigType::Integer}.defaultValue(10'000).withConstraint(gValidateUint32)},
273 {
"database.cassandra.max_read_requests_outstanding",
274 ConfigValue{ConfigType::Integer}.defaultValue(100'000).withConstraint(gValidateUint32)},
275 {
"database.cassandra.threads",
276 ConfigValue{ConfigType::Integer}
277 .defaultValue(
static_cast<uint32_t
>(std::thread::hardware_concurrency()))
278 .withConstraint(gValidateUint32)},
279 {
"database.cassandra.core_connections_per_host",
280 ConfigValue{ConfigType::Integer}.defaultValue(1).withConstraint(gValidateUint16)},
281 {
"database.cassandra.queue_size_io", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint16)},
282 {
"database.cassandra.write_batch_size",
283 ConfigValue{ConfigType::Integer}.defaultValue(20).withConstraint(gValidateUint16)},
284 {
"database.cassandra.connect_timeout", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)
286 {
"database.cassandra.request_timeout", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)
288 {
"database.cassandra.username", ConfigValue{ConfigType::String}.optional()},
289 {
"database.cassandra.password", ConfigValue{ConfigType::String}.optional()},
290 {
"database.cassandra.certfile", ConfigValue{ConfigType::String}.optional()},
292 {
"allow_no_etl", ConfigValue{ConfigType::Boolean}.defaultValue(
false)},
294 {
"etl_sources.[].ip", Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidateIp)}},
295 {
"etl_sources.[].ws_port", Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidatePort)}},
296 {
"etl_sources.[].grpc_port", Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidatePort)}},
298 {
"forwarding.cache_timeout",
299 ConfigValue{ConfigType::Double}.defaultValue(0.0).withConstraint(gValidatePositiveDouble)},
300 {
"forwarding.request_timeout",
301 ConfigValue{ConfigType::Double}.defaultValue(10.0).withConstraint(gValidatePositiveDouble)},
303 {
"rpc.cache_timeout", ConfigValue{ConfigType::Double}.defaultValue(0.0).withConstraint(gValidatePositiveDouble)},
305 {
"num_markers", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateNumMarkers)},
307 {
"dos_guard.whitelist.[]", Array{ConfigValue{ConfigType::String}.optional()}},
308 {
"dos_guard.max_fetches", ConfigValue{ConfigType::Integer}.defaultValue(1000'000u).withConstraint(gValidateUint32)
310 {
"dos_guard.max_connections", ConfigValue{ConfigType::Integer}.defaultValue(20u).withConstraint(gValidateUint32)},
311 {
"dos_guard.max_requests", ConfigValue{ConfigType::Integer}.defaultValue(20u).withConstraint(gValidateUint32)},
312 {
"dos_guard.sweep_interval",
313 ConfigValue{ConfigType::Double}.defaultValue(1.0).withConstraint(gValidatePositiveDouble)},
316 ConfigValue{ConfigType::Integer}.defaultValue(std::thread::hardware_concurrency()).withConstraint(gValidateUint32)
319 {
"server.ip", ConfigValue{ConfigType::String}.withConstraint(gValidateIp)},
320 {
"server.port", ConfigValue{ConfigType::Integer}.withConstraint(gValidatePort)},
321 {
"server.max_queue_size", ConfigValue{ConfigType::Integer}.defaultValue(0).withConstraint(gValidateUint32)},
322 {
"server.local_admin", ConfigValue{ConfigType::Boolean}.optional()},
323 {
"server.admin_password", ConfigValue{ConfigType::String}.optional()},
324 {
"server.processing_policy",
325 ConfigValue{ConfigType::String}.defaultValue(
"parallel").withConstraint(gValidateProcessingPolicy)},
326 {
"server.parallel_requests_limit", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint16)},
327 {
"server.ws_max_sending_queue_size",
328 ConfigValue{ConfigType::Integer}.defaultValue(1500).withConstraint(gValidateUint32)},
329 {
"server.__ng_web_server", ConfigValue{ConfigType::Boolean}.defaultValue(
false)},
331 {
"prometheus.enabled", ConfigValue{ConfigType::Boolean}.defaultValue(
true)},
332 {
"prometheus.compress_reply", ConfigValue{ConfigType::Boolean}.defaultValue(
true)},
334 {
"io_threads", ConfigValue{ConfigType::Integer}.defaultValue(2).withConstraint(gValidateIOThreads)},
336 {
"subscription_workers", ConfigValue{ConfigType::Integer}.defaultValue(1).withConstraint(gValidateUint32)},
338 {
"graceful_period", ConfigValue{ConfigType::Double}.defaultValue(10.0).withConstraint(gValidatePositiveDouble)},
340 {
"cache.num_diffs", ConfigValue{ConfigType::Integer}.defaultValue(32).withConstraint(gValidateUint16)},
341 {
"cache.num_markers", ConfigValue{ConfigType::Integer}.defaultValue(48).withConstraint(gValidateUint16)},
342 {
"cache.num_cursors_from_diff", ConfigValue{ConfigType::Integer}.defaultValue(0).withConstraint(gValidateUint16)},
343 {
"cache.num_cursors_from_account", ConfigValue{ConfigType::Integer}.defaultValue(0).withConstraint(gValidateUint16)
345 {
"cache.page_fetch_size", ConfigValue{ConfigType::Integer}.defaultValue(512).withConstraint(gValidateUint16)},
346 {
"cache.load", ConfigValue{ConfigType::String}.defaultValue(
"async").withConstraint(gValidateLoadMode)},
348 {
"log_channels.[].channel", Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidateChannelName)}
350 {
"log_channels.[].log_level",
351 Array{ConfigValue{ConfigType::String}.optional().withConstraint(gValidateLogLevelName)}},
353 {
"log_level", ConfigValue{ConfigType::String}.defaultValue(
"info").withConstraint(gValidateLogLevelName)},
356 ConfigValue{ConfigType::String}.defaultValue(
357 R
"(%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%)"
360 {"log_to_console", ConfigValue{ConfigType::Boolean}.defaultValue(
false)},
362 {
"log_directory", ConfigValue{ConfigType::String}.optional()},
364 {
"log_rotation_size", ConfigValue{ConfigType::Integer}.defaultValue(2048).withConstraint(gValidateLogSize)},
366 {
"log_directory_max_size",
367 ConfigValue{ConfigType::Integer}.defaultValue(50 * 1024).withConstraint(gValidateLogSize)},
369 {
"log_rotation_hour_interval",
370 ConfigValue{ConfigType::Integer}.defaultValue(12).withConstraint(gValidateLogRotationTime)},
372 {
"log_tag_style", ConfigValue{ConfigType::String}.defaultValue(
"none").withConstraint(gValidateLogTag)},
374 {
"extractor_threads", ConfigValue{ConfigType::Integer}.defaultValue(1u).withConstraint(gValidateUint32)},
376 {
"read_only", ConfigValue{ConfigType::Boolean}.defaultValue(
false)},
378 {
"txn_threshold", ConfigValue{ConfigType::Integer}.defaultValue(0).withConstraint(gValidateUint16)},
380 {
"start_sequence", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)},
382 {
"finish_sequence", ConfigValue{ConfigType::Integer}.optional().withConstraint(gValidateUint32)},
384 {
"ssl_cert_file", ConfigValue{ConfigType::String}.optional()},
386 {
"ssl_key_file", ConfigValue{ConfigType::String}.optional()},
388 {
"api_version.default",
391 ConfigValue{ConfigType::Integer}.defaultValue(
rpc::kAPI_VERSION_MIN).withConstraint(gValidateApiVersion)},
393 ConfigValue{ConfigType::Integer}.defaultValue(
rpc::kAPI_VERSION_MAX).withConstraint(gValidateApiVersion)},
395 {
"migration.full_scan_threads", ConfigValue{ConfigType::Integer}.defaultValue(2).withConstraint(gValidateUint32)},
396 {
"migration.full_scan_jobs", ConfigValue{ConfigType::Integer}.defaultValue(4).withConstraint(gValidateUint32)},
397 {
"migration.cursors_per_job", ConfigValue{ConfigType::Integer}.defaultValue(100).withConstraint(gValidateUint32)}},
View for array structure for config.
Definition ArrayView.hpp:42
Array definition to store multiple values provided by the user from Json/Yaml.
Definition Array.hpp:41
All the config data will be stored and extracted from this class.
Definition ConfigDefinition.hpp:54
auto begin() const
Returns an iterator to the beginning of the configuration map.
Definition ConfigDefinition.hpp:202
std::size_t arraySize(std::string_view prefix) const
Returns the size of an Array.
Definition ConfigDefinition.cpp:143
ArrayView getArray(std::string_view prefix) const
Returns the specified Array object from ClioConfigDefinition.
Definition ConfigDefinition.cpp:82
static std::chrono::milliseconds toMilliseconds(float value)
Method to convert a float seconds value to milliseconds.
Definition ConfigDefinition.cpp:122
auto end() const
Returns an iterator to the end of the configuration map.
Definition ConfigDefinition.hpp:213
std::optional< std::vector< Error > > parse(ConfigFileInterface const &config)
Parses the configuration file.
Definition ConfigDefinition.cpp:157
bool contains(std::string_view key) const
Checks if a key is present in the configuration map.
Definition ConfigDefinition.cpp:99
ObjectView getObject(std::string_view prefix, std::optional< std::size_t > idx=std::nullopt) const
Returns the ObjectView specified with the prefix.
Definition ConfigDefinition.cpp:61
bool hasItemsWithPrefix(std::string_view key) const
Checks if any key in config starts with "key".
Definition ConfigDefinition.cpp:105
ClioConfigDefinition(std::initializer_list< KeyValuePair > pair)
Constructs a new ClioConfigDefinition.
Definition ConfigDefinition.cpp:51
Array const & asArray(std::string_view key) const
Returns the Array object associated with the specified key.
Definition ConfigDefinition.cpp:136
ValueView getValueView(std::string_view fullKey) const
Returns the specified ValueView object associated with the key.
Definition ConfigDefinition.cpp:111
std::optional< T > maybeValue(std::string_view fullKey) const
Returns the specified value of given string of type T if type and value exists.
Definition ConfigDefinition.hpp:191
T get(std::string_view fullKey) const
Returns the specified value of given string if value exists.
Definition ConfigDefinition.hpp:108
ValueView getValueInArray(std::string_view fullKey, std::size_t index) const
Returns the specified ValueView object in an array with a given index.
Definition ConfigDefinition.cpp:129
The interface for configuration files.
Definition ConfigFileInterface.hpp:35
Provides a view into a subset of configuration data defined by a prefix.
Definition ObjectView.hpp:40
Provides view into ConfigValues that represents values in Clio Config.
Definition ValueView.hpp:46
T getValueImpl() const
Retrieves the stored value as the specified type T.
Definition ValueView.hpp:165
std::optional< T > asOptional() const
Returns an optional value of the specified type T if valid.
Definition ValueView.hpp:193
static constexpr uint32_t kAPI_VERSION_MIN
Minimum API version supported by this build.
Definition APIVersion.hpp:38
static constexpr uint32_t kAPI_VERSION_MAX
Maximum API version supported by this build.
Definition APIVersion.hpp:43
static constexpr uint32_t kAPI_VERSION_DEFAULT
Default API version to use if no version is specified by clients.
Definition APIVersion.hpp:33