Validate config
This commit is contained in:
118
src/config.cpp
118
src/config.cpp
@@ -15,6 +15,10 @@ ConfigParser::load_from_file(const std::string &file_path) {
|
|||||||
parse_commit_config(toml_data, config.commit);
|
parse_commit_config(toml_data, config.commit);
|
||||||
parse_subscription_config(toml_data, config.subscription);
|
parse_subscription_config(toml_data, config.subscription);
|
||||||
|
|
||||||
|
if (!validate_config(config)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << "Error parsing config file '" << file_path << "': " << e.what()
|
std::cerr << "Error parsing config file '" << file_path << "': " << e.what()
|
||||||
@@ -33,6 +37,10 @@ ConfigParser::parse_toml_string(const std::string &toml_content) {
|
|||||||
parse_commit_config(toml_data, config.commit);
|
parse_commit_config(toml_data, config.commit);
|
||||||
parse_subscription_config(toml_data, config.subscription);
|
parse_subscription_config(toml_data, config.subscription);
|
||||||
|
|
||||||
|
if (!validate_config(config)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << "Error parsing TOML content: " << e.what() << std::endl;
|
std::cerr << "Error parsing TOML content: " << e.what() << std::endl;
|
||||||
@@ -100,4 +108,114 @@ void ConfigParser::parse_subscription_config(const auto &toml_data,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConfigParser::validate_config(const Config &config) {
|
||||||
|
bool valid = true;
|
||||||
|
|
||||||
|
// Validate server configuration
|
||||||
|
if (config.server.port <= 0 || config.server.port > 65535) {
|
||||||
|
std::cerr
|
||||||
|
<< "Configuration error: server.port must be between 1 and 65535, got "
|
||||||
|
<< config.server.port << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.server.max_request_size_bytes == 0) {
|
||||||
|
std::cerr << "Configuration error: server.max_request_size_bytes must be "
|
||||||
|
"greater than 0"
|
||||||
|
<< std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.server.max_request_size_bytes > 100 * 1024 * 1024) { // 100MB limit
|
||||||
|
std::cerr << "Configuration error: server.max_request_size_bytes too large "
|
||||||
|
"(max 100MB), got "
|
||||||
|
<< config.server.max_request_size_bytes << " bytes" << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.server.accept_threads < 1 || config.server.accept_threads > 100) {
|
||||||
|
std::cerr << "Configuration error: server.accept_threads must be between 1 "
|
||||||
|
"and 100, got "
|
||||||
|
<< config.server.accept_threads << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.server.network_threads < 1 ||
|
||||||
|
config.server.network_threads > 1000) {
|
||||||
|
std::cerr << "Configuration error: server.network_threads must be between "
|
||||||
|
"1 and 1000, got "
|
||||||
|
<< config.server.network_threads << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.server.event_batch_size < 1 ||
|
||||||
|
config.server.event_batch_size > 10000) {
|
||||||
|
std::cerr << "Configuration error: server.event_batch_size must be between "
|
||||||
|
"1 and 10000, got "
|
||||||
|
<< config.server.event_batch_size << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate commit configuration
|
||||||
|
if (config.commit.min_request_id_length < 8 ||
|
||||||
|
config.commit.min_request_id_length > 256) {
|
||||||
|
std::cerr << "Configuration error: commit.min_request_id_length must be "
|
||||||
|
"between 8 and 256, got "
|
||||||
|
<< config.commit.min_request_id_length << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.commit.request_id_retention_hours.count() < 1 ||
|
||||||
|
config.commit.request_id_retention_hours.count() > 8760) { // 1 year max
|
||||||
|
std::cerr << "Configuration error: commit.request_id_retention_hours must "
|
||||||
|
"be between 1 and 8760, got "
|
||||||
|
<< config.commit.request_id_retention_hours.count() << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.commit.request_id_retention_versions == 0) {
|
||||||
|
std::cerr << "Configuration error: commit.request_id_retention_versions "
|
||||||
|
"must be greater than 0"
|
||||||
|
<< std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate subscription configuration
|
||||||
|
if (config.subscription.max_buffer_size_bytes == 0) {
|
||||||
|
std::cerr << "Configuration error: subscription.max_buffer_size_bytes must "
|
||||||
|
"be greater than 0"
|
||||||
|
<< std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.subscription.max_buffer_size_bytes >
|
||||||
|
1024 * 1024 * 1024) { // 1GB limit
|
||||||
|
std::cerr << "Configuration error: subscription.max_buffer_size_bytes too "
|
||||||
|
"large (max 1GB), got "
|
||||||
|
<< config.subscription.max_buffer_size_bytes << " bytes"
|
||||||
|
<< std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.subscription.keepalive_interval.count() < 1 ||
|
||||||
|
config.subscription.keepalive_interval.count() > 3600) { // 1 hour max
|
||||||
|
std::cerr << "Configuration error: subscription.keepalive_interval must be "
|
||||||
|
"between 1 and 3600 seconds, got "
|
||||||
|
<< config.subscription.keepalive_interval.count() << std::endl;
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cross-validation checks
|
||||||
|
if (config.server.max_request_size_bytes >
|
||||||
|
config.subscription.max_buffer_size_bytes) {
|
||||||
|
std::cerr << "Configuration warning: server.max_request_size_bytes ("
|
||||||
|
<< config.server.max_request_size_bytes
|
||||||
|
<< ") is larger than subscription.max_buffer_size_bytes ("
|
||||||
|
<< config.subscription.max_buffer_size_bytes << ")" << std::endl;
|
||||||
|
// This is just a warning, not a validation failure
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace weaseldb
|
} // namespace weaseldb
|
||||||
|
|||||||
@@ -93,6 +93,19 @@ public:
|
|||||||
static std::optional<Config>
|
static std::optional<Config>
|
||||||
parse_toml_string(const std::string &toml_content);
|
parse_toml_string(const std::string &toml_content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate configuration values are within reasonable bounds.
|
||||||
|
*
|
||||||
|
* This function performs comprehensive validation of all configuration
|
||||||
|
* parameters and writes detailed diagnostic messages to stderr for any
|
||||||
|
* validation failures or warnings encountered.
|
||||||
|
*
|
||||||
|
* @param config Configuration object to validate
|
||||||
|
* @return true if configuration is valid, false otherwise
|
||||||
|
* @note Validation errors and warnings are written to stderr
|
||||||
|
*/
|
||||||
|
static bool validate_config(const Config &config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Generic configuration parsing utilities
|
// Generic configuration parsing utilities
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
Reference in New Issue
Block a user