Skip to content

Commit

Permalink
Attempt at fixing build
Browse files Browse the repository at this point in the history
  • Loading branch information
adams85 committed Mar 1, 2024
1 parent f9b4b81 commit 7269ed5
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 59 deletions.
13 changes: 9 additions & 4 deletions include/configcat/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,17 @@ namespace configcat {
std::shared_ptr<Segments> segments;
std::shared_ptr<Settings> settings;

std::shared_ptr<Segments> ensureSegments() const { return segments ? segments : std::make_shared<Segments>(); }
std::shared_ptr<Settings> ensureSettings() const { return settings ? settings : std::make_shared<Settings>(); }
std::shared_ptr<Segments> getSegmentsOrEmpty() const { return segments ? segments : std::make_shared<Segments>(); }
std::shared_ptr<Settings> getSettingsOrEmpty() const { return settings ? settings : std::make_shared<Settings>(); }

Config() : segments(std::make_shared<Segments>()), settings(std::make_shared<Settings>()) {}
Config() {}

Config(const Config& other) : Config() { *this = other; }
Config(const Config& other)
: preferences(other.preferences)
, segments(other.segments ? std::make_shared<Segments>(*other.segments) : nullptr)
, settings(other.settings ? std::make_shared<Settings>(*other.settings) : nullptr) {
this->fixupSaltAndSegments();
}

Config& operator=(const Config& other) {
this->preferences = other.preferences;
Expand Down
4 changes: 2 additions & 2 deletions include/configcat/configcatclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ class ConfigCatClient {
ConfigCatClient(const std::string& sdkKey, const ConfigCatOptions& options);

template<typename ValueType>
ValueType _getValue(const std::string& key, const ValueType& defaultValue, const std::shared_ptr<ConfigCatUser>& user = nullptr) const;
typename std::decay_t<ValueType> _getValue(const std::string& key, ValueType&& defaultValue, const std::shared_ptr<ConfigCatUser>& user = nullptr) const;

template<typename ValueType>
EvaluationDetails<ValueType> _getValueDetails(const std::string& key, ValueType defaultValue, const std::shared_ptr<ConfigCatUser>& user = nullptr) const;
EvaluationDetails<typename std::decay_t<ValueType>> _getValueDetails(const std::string& key, ValueType&& defaultValue, const std::shared_ptr<ConfigCatUser>& user = nullptr) const;

SettingResult getSettings() const;

Expand Down
17 changes: 6 additions & 11 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,14 @@ namespace configcat {
return alt;
}
else if constexpr (is_same_v<T, int32_t>) {
return to_string(alt);
return string_format("%d", alt);
}
else if constexpr (is_same_v<T, double>) {
auto str = to_string(alt);
// Drop unnecessary '0' characters at the end of the string and keep format 0.0 for zero double
auto pos = str.find_last_not_of('0');
if (pos != string::npos && str[pos] == '.') {
--pos;
}
return str.erase(pos + 1, string::npos);
return numberToString(alt);
}
else {
static_assert(false, "Non-exhaustive visitor.");
throw new runtime_error(string("Unexpected alternate type: ") + typeid(T).name());
// static_assert(false, "Non-exhaustive visitor.");
}
}, *this);
}
Expand Down Expand Up @@ -383,8 +378,8 @@ namespace configcat {

void from_json(const json& j, Config& config) {
if (auto it = j.find(Config::kPreferences); it != j.end()) it->get_to(config.preferences);
if (auto it = j.find(Config::kSegments); it != j.end()) it->get_to(*config.ensureSegments());
if (auto it = j.find(Config::kSettings); it != j.end()) it->get_to(*config.ensureSettings());
if (auto it = j.find(Config::kSegments); it != j.end()) it->get_to(*(config.segments = make_shared<Segments>()));
if (auto it = j.find(Config::kSettings); it != j.end()) it->get_to(*(config.settings = make_shared<Settings>()));
}

const shared_ptr<const Config> Config::empty = make_shared<Config>();
Expand Down
73 changes: 38 additions & 35 deletions src/configcatclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,15 @@ double ConfigCatClient::getValue(const std::string& key, double defaultValue, co
}

std::string ConfigCatClient::getValue(const std::string& key, const char* defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
return _getValue(key, string(defaultValue), user);
return _getValue<const string&>(key, defaultValue, user);
}

std::string ConfigCatClient::getValue(const std::string& key, const std::string& defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
return _getValue(key, defaultValue, user);
}

std::optional<Value> ConfigCatClient::getValue(const std::string& key, const std::shared_ptr<ConfigCatUser>& user) const {
return _getValue(key, static_cast<optional<Value>>(nullopt), user);
return _getValue<const optional<Value>&>(key, nullopt, user);
}

EvaluationDetails<bool> ConfigCatClient::getValueDetails(const std::string& key, bool defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
Expand All @@ -185,28 +185,30 @@ EvaluationDetails<std::string> ConfigCatClient::getValueDetails(const std::strin
}

EvaluationDetails<std::string> ConfigCatClient::getValueDetails(const std::string& key, const char* defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
return _getValueDetails(key, string(defaultValue), user);
return _getValueDetails<const string&>(key, defaultValue, user);
}

EvaluationDetails<std::optional<Value>> ConfigCatClient::getValueDetails(const std::string& key, const std::shared_ptr<ConfigCatUser>& user) const {
return _getValueDetails(key, static_cast<optional<Value>>(nullopt), user);
return _getValueDetails<const optional<Value>&>(key, nullopt, user);
}

template<typename ValueType>
EvaluationDetails<ValueType> ConfigCatClient::_getValueDetails(const std::string& key, ValueType defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
EvaluationDetails<typename std::decay_t<ValueType>> ConfigCatClient::_getValueDetails(const std::string& key, ValueType&& defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
using T = typename std::decay_t<ValueType>;

try {
auto settingResult = getSettings();
auto& settings = settingResult.settings;
auto& fetchTime = settingResult.fetchTime;
if (!settings) {
LogEntry logEntry(logger, LOG_LEVEL_ERROR, 1000);
if constexpr (is_same_v<ValueType, optional<Value>>) {
if constexpr (is_same_v<T, optional<Value>>) {
logEntry << "Config JSON is not present when evaluating setting '" << key << "'. Returning std::nullopt.";
}
else {
logEntry << "Config JSON is not present when evaluating setting '" << key << "'. Returning the `defaultValue` parameter that you specified in your application: '" << defaultValue << "'.";
}
auto details = EvaluationDetails<ValueType>::fromError(key, defaultValue, logEntry.getMessage());
auto details = EvaluationDetails<T>::fromError(key, defaultValue, logEntry.getMessage());
hooks->invokeOnFlagEvaluated(details);
return details;
}
Expand All @@ -219,7 +221,7 @@ EvaluationDetails<ValueType> ConfigCatClient::_getValueDetails(const std::string
keys.emplace_back("'" + keyValue.first + "'");
}
LogEntry logEntry(logger, LOG_LEVEL_ERROR, 1001);
if constexpr (is_same_v<ValueType, optional<Value>>) {
if constexpr (is_same_v<T, optional<Value>>) {
logEntry <<
"Failed to evaluate setting '" << key << "' (the key was not found in config JSON). "
"Returning the `defaultValue` parameter that you specified in your application: '" << defaultValue << "'. "
Expand All @@ -230,25 +232,25 @@ EvaluationDetails<ValueType> ConfigCatClient::_getValueDetails(const std::string
"Failed to evaluate setting '" << key << "' (the key was not found in config JSON). "
"Returning std::nullopt. Available keys: " << keys << ".";
}
auto details = EvaluationDetails<ValueType>::fromError(key, defaultValue, logEntry.getMessage());
auto details = EvaluationDetails<T>::fromError(key, defaultValue, logEntry.getMessage());
hooks->invokeOnFlagEvaluated(details);
return details;
}

const auto& effectiveUser = user ? user : this->defaultUser;
return evaluate<ValueType>(key, defaultValue, effectiveUser, setting->second, fetchTime);
return evaluate<T>(key, defaultValue, effectiveUser, setting->second, fetchTime);
}
catch (...) {
const auto& ex = unwrapException(std::current_exception());
LogEntry logEntry(logger, LOG_LEVEL_ERROR, 1002, ex);
logEntry << "Error occurred in the `getValueDetails` method while evaluating setting '" << key << "'. ";
if constexpr (is_same_v<ValueType, optional<Value>>) {
if constexpr (is_same_v<T, optional<Value>>) {
logEntry << "Returning std::nullopt.";
}
else {
logEntry << "Returning the `defaultValue` parameter that you specified in your application: '" << defaultValue << "'.";
}
const auto details = EvaluationDetails<ValueType>::fromError(key, defaultValue, logEntry.getMessage(), ex);
const auto details = EvaluationDetails<T>::fromError(key, defaultValue, logEntry.getMessage(), ex);
hooks->invokeOnFlagEvaluated(details);
return details;
}
Expand Down Expand Up @@ -335,7 +337,7 @@ std::unordered_map<std::string, Value> ConfigCatClient::getAllValues(const std::
for (auto keyValue : *settings) {
auto& key = keyValue.first;
auto details = evaluate<Value>(key, nullopt, effectiveUser, keyValue.second, fetchTime);
result.insert({ key, details.value });
result.insert({ key, move(details.value) });
}

return result;
Expand Down Expand Up @@ -376,20 +378,22 @@ std::vector<EvaluationDetails<Value>> ConfigCatClient::getAllValueDetails(const
}

template<typename ValueType>
ValueType ConfigCatClient::_getValue(const std::string& key, const ValueType& defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
typename std::decay_t<ValueType> ConfigCatClient::_getValue(const std::string& key, ValueType&& defaultValue, const std::shared_ptr<ConfigCatUser>& user) const {
using T = typename std::decay_t<ValueType>;

try {
auto settingResult = getSettings();
auto& settings = settingResult.settings;
auto& fetchTime = settingResult.fetchTime;
if (!settings) {
LogEntry logEntry(logger, LOG_LEVEL_ERROR, 1000);
if constexpr (is_same_v<ValueType, optional<Value>>) {
if constexpr (is_same_v<T, optional<Value>>) {
logEntry << "Config JSON is not present when evaluating setting '" << key << "'. Returning std::nullopt.";
}
else {
logEntry << "Config JSON is not present when evaluating setting '" << key << "'. Returning the `defaultValue` parameter that you specified in your application: '" << defaultValue << "'.";
}
hooks->invokeOnFlagEvaluated(EvaluationDetails<ValueType>::fromError(key, defaultValue, logEntry.getMessage()));
hooks->invokeOnFlagEvaluated(EvaluationDetails<T>::fromError(key, defaultValue, logEntry.getMessage()));
return defaultValue;
}

Expand All @@ -401,7 +405,7 @@ ValueType ConfigCatClient::_getValue(const std::string& key, const ValueType& de
keys.emplace_back("'" + keyValue.first + "'");
}
LogEntry logEntry(logger, LOG_LEVEL_ERROR, 1001);
if constexpr (is_same_v<ValueType, optional<Value>>) {
if constexpr (is_same_v<T, optional<Value>>) {
logEntry <<
"Failed to evaluate setting '" << key << "' (the key was not found in config JSON). "
"Returning the `defaultValue` parameter that you specified in your application: '" << defaultValue << "'. "
Expand All @@ -412,26 +416,26 @@ ValueType ConfigCatClient::_getValue(const std::string& key, const ValueType& de
"Failed to evaluate setting '" << key << "' (the key was not found in config JSON). "
"Returning std::nullopt. Available keys: " << keys << ".";
}
hooks->invokeOnFlagEvaluated(EvaluationDetails<ValueType>::fromError(key, defaultValue, logEntry.getMessage()));
hooks->invokeOnFlagEvaluated(EvaluationDetails<T>::fromError(key, defaultValue, logEntry.getMessage()));
return defaultValue;
}

const auto& effectiveUser = user ? user : this->defaultUser;
const auto details = evaluate<ValueType>(key, defaultValue, effectiveUser, setting->second, fetchTime);
const auto details = evaluate<T>(key, defaultValue, effectiveUser, setting->second, fetchTime);

return details.value;
}
catch (...) {
const auto& ex = unwrapException(std::current_exception());
LogEntry logEntry(logger, LOG_LEVEL_ERROR, 1002, ex);
logEntry << "Error occurred in the `getValue` method while evaluating setting '" << key << "'. ";
if constexpr (is_same_v<ValueType, optional<Value>>) {
if constexpr (is_same_v<T, optional<Value>>) {
logEntry << "Returning std::nullopt.";
}
else {
logEntry << "Returning the `defaultValue` parameter that you specified in your application: '" << defaultValue << "'.";
}
auto details = EvaluationDetails<ValueType>::fromError(key, defaultValue, logEntry.getMessage(), ex);
auto details = EvaluationDetails<T>::fromError(key, defaultValue, logEntry.getMessage(), ex);
hooks->invokeOnFlagEvaluated(details);
return defaultValue;
}
Expand All @@ -443,37 +447,36 @@ EvaluationDetails<ValueType> ConfigCatClient::evaluate(const std::string& key,
const std::shared_ptr<ConfigCatUser>& effectiveUser,
const Setting& setting,
double fetchTime) const {

EvaluateContext evaluateContext(key, setting, effectiveUser);
std::optional<Value> returnValue;
auto& evaluateResult = rolloutEvaluator->evaluate(defaultValue, evaluateContext, returnValue);
auto evaluateResult = rolloutEvaluator->evaluate(defaultValue, evaluateContext, returnValue);

ValueType value;
if constexpr (is_same_v<ValueType, bool> || is_same_v<ValueType, std::string> || is_same_v<ValueType, int32_t> || is_same_v<ValueType, double>) {
if constexpr (is_same_v<ValueType, bool> || is_same_v<ValueType, string> || is_same_v<ValueType, int32_t> || is_same_v<ValueType, double>) {
// RolloutEvaluator::evaluate makes sure that this variant access is always valid.
value = std::get<ValueType>(*returnValue);
}
else if constexpr (is_same_v<ValueType, Value>) {
value = *returnValue;
}
else if constexpr (is_same_v<ValueType, std::optional<Value>>) {
else if constexpr (is_same_v<ValueType, optional<Value>>) {
value = returnValue;
}
else {
static_assert(false, typeid(T).name());
throw new runtime_error(string("Unexpected return value type: ") + typeid(ValueType).name());
//static_assert(false, "Unsupported value type.");
}

EvaluationDetails<ValueType> details(key,
value,
evaluateResult.selectedValue.variationId,
time_point<system_clock, duration<double>>(duration<double>(fetchTime)),
effectiveUser,
false,
nullopt,
nullopt,
evaluateResult.targetingRule,
evaluateResult.percentageOption);
value,
evaluateResult.selectedValue.variationId,
time_point<system_clock, duration<double>>(duration<double>(fetchTime)),
effectiveUser,
false,
nullopt,
nullopt,
evaluateResult.targetingRule,
evaluateResult.percentageOption);
hooks->invokeOnFlagEvaluated(details);
return details;
}
Expand Down
10 changes: 5 additions & 5 deletions src/configservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ SettingResult ConfigService::getSettings() {
auto now = chrono::steady_clock::now();
auto [ entry, _ ] = fetchIfOlder(getUtcNowSecondsSinceEpoch() - lazyPollingMode.cacheRefreshIntervalInSeconds);
auto config = cachedEntry->config;
return { (cachedEntry != ConfigEntry::empty && config) ? config->ensureSettings() : nullptr, entry->fetchTime};
return { (cachedEntry != ConfigEntry::empty && config) ? config->getSettingsOrEmpty() : nullptr, entry->fetchTime};
} else if (pollingMode->getPollingIdentifier() == AutoPollingMode::kIdentifier && !initialized) {
auto& autoPollingMode = (AutoPollingMode&)*pollingMode;
auto elapsedTime = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();
Expand All @@ -63,14 +63,14 @@ SettingResult ConfigService::getSettings() {
if (!initialized) {
setInitialized();
auto config = cachedEntry->config;
return { (cachedEntry != ConfigEntry::empty && config) ? config->ensureSettings() : nullptr, cachedEntry->fetchTime };
return { (cachedEntry != ConfigEntry::empty && config) ? config->getSettingsOrEmpty() : nullptr, cachedEntry->fetchTime };
}
}
}

auto [ entry, _ ] = fetchIfOlder(kDistantPast, true);
auto config = entry->config;
return { (cachedEntry != ConfigEntry::empty && config) ? config->ensureSettings() : nullptr, entry->fetchTime };
return { (cachedEntry != ConfigEntry::empty && config) ? config->getSettingsOrEmpty() : nullptr, entry->fetchTime };
}

RefreshResult ConfigService::refresh() {
Expand Down Expand Up @@ -122,7 +122,7 @@ tuple<shared_ptr<const ConfigEntry>, string> ConfigService::fetchIfOlder(double
auto entry = readCache();
if (entry != ConfigEntry::empty && entry->eTag != cachedEntry->eTag) {
cachedEntry = const_pointer_cast<ConfigEntry>(entry);
hooks->invokeOnConfigChanged(entry->config->ensureSettings());
hooks->invokeOnConfigChanged(entry->config->getSettingsOrEmpty());
}

// Cache isn't expired
Expand Down Expand Up @@ -166,7 +166,7 @@ tuple<shared_ptr<const ConfigEntry>, string> ConfigService::fetchIfOlder(double
if (response.isFetched()) {
cachedEntry = const_pointer_cast<ConfigEntry>(response.entry);
writeCache(cachedEntry);
hooks->invokeOnConfigChanged(cachedEntry->config->ensureSettings());
hooks->invokeOnConfigChanged(cachedEntry->config->getSettingsOrEmpty());
} else if ((response.notModified() || !response.isTransientError) && cachedEntry != ConfigEntry::empty) {
cachedEntry->fetchTime = getUtcNowSecondsSinceEpoch();
writeCache(cachedEntry);
Expand Down
2 changes: 1 addition & 1 deletion src/fileoverridedatasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void FileOverrideDataSource::reloadFileContent() {
if (fileLastWriteTime != lastWriteTime) {
fileLastWriteTime = lastWriteTime;
auto config = Config::fromFile(filePath);
overrides = config->ensureSettings();
overrides = config->getSettingsOrEmpty();
}
} catch (filesystem::filesystem_error exception) {
LOG_ERROR(1302) << "Failed to read the local config file '" << filePath << "'. " << exception.what();
Expand Down
Loading

0 comments on commit 7269ed5

Please sign in to comment.