Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion providers/flagd/src/sync/grpc/grpc_sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,11 @@ GrpcSync::StreamResult GrpcSync::ProcessStream(
continue;
}

UpdateFlags(raw);
absl::Status status = UpdateFlags(raw);
if (!status.ok()) {
LOG(ERROR) << "Failed to update flags: " << status;
continue;
}
Comment thread
m-olko marked this conversation as resolved.

if (!connected) {
connected = true;
Expand Down
20 changes: 11 additions & 9 deletions providers/flagd/src/sync/sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <nlohmann/json.hpp>

#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "embedded_schemas.h"

using Json = nlohmann::json;
Expand Down Expand Up @@ -38,13 +39,13 @@ class FlagSync::Validator {
validator.set_root_schema(Json::parse(schema::schemas.at("flagd.json")));
}

bool Validate(const Json& json) const {
absl::Status Validate(const Json& json) const {
Comment thread
m-olko marked this conversation as resolved.
try {
validator.validate(json);
return true;
return absl::OkStatus();
} catch (const std::exception& e) {
LOG(ERROR) << "Flag configuration validation failed: " << e.what();
return false;
return absl::InvalidArgumentError(
absl::StrCat("Flag configuration validation failed: ", e.what()));
}
}
};
Expand All @@ -58,12 +59,11 @@ FlagSync::FlagSync()

FlagSync::~FlagSync() = default;

void FlagSync::UpdateFlags(const nlohmann::json& new_json) {
absl::Status FlagSync::UpdateFlags(const nlohmann::json& new_json) {
Comment thread
m-olko marked this conversation as resolved.
if (validator_) {
if (!validator_->Validate(new_json)) {
// Validation failed, do not update flags.
LOG(ERROR) << "Flag configuration validation failed, skipping update.";
return;
absl::Status status = validator_->Validate(new_json);
if (!status.ok()) {
return status;
}
}

Expand All @@ -83,6 +83,8 @@ void FlagSync::UpdateFlags(const nlohmann::json& new_json) {
current_flags_ = std::move(new_flags_snapshot);
global_metadata_ = std::move(new_metadata_snapshot);
}

return absl::OkStatus();
}

void FlagSync::ClearFlags() {
Expand Down
2 changes: 1 addition & 1 deletion providers/flagd/src/sync/sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class FlagSync {
std::shared_ptr<const nlohmann::json> GetMetadata() const;

protected:
void UpdateFlags(const nlohmann::json& new_json);
absl::Status UpdateFlags(const nlohmann::json& new_json);
Comment thread
m-olko marked this conversation as resolved.
void ClearFlags();

private:
Expand Down
42 changes: 21 additions & 21 deletions providers/flagd/tests/evaluator/evaluator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class TestableSync : public flagd::FlagSync {
}
absl::Status Shutdown() override { return absl::OkStatus(); }

void TriggerUpdate(const nlohmann::json& new_json) {
this->UpdateFlags(new_json);
absl::Status TriggerUpdate(const nlohmann::json& new_json) {
return this->UpdateFlags(new_json);
}
Comment thread
m-olko marked this conversation as resolved.
};

Expand Down Expand Up @@ -46,7 +46,7 @@ TEST_F(EvaluatorTest, ResolveBooleanSuccess) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -63,7 +63,7 @@ TEST_F(EvaluatorTest, ResolveBooleanFlagNotFound) {
nlohmann::json flags = nlohmann::json::parse(R"({
"flags": {}
})");
sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -89,7 +89,7 @@ TEST_F(EvaluatorTest, ResolveBooleanTypeMismatch) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -123,7 +123,7 @@ TEST_F(EvaluatorTest, ResolveBooleanMetadata) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -154,7 +154,7 @@ TEST_F(EvaluatorTest, ResolveBooleanVariantNotFound) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -183,7 +183,7 @@ TEST_F(EvaluatorTest, ResolveStringSuccess) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -209,7 +209,7 @@ TEST_F(EvaluatorTest, ResolveIntegerSuccess) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -235,7 +235,7 @@ TEST_F(EvaluatorTest, ResolveDoubleSuccess) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -266,7 +266,7 @@ TEST_F(EvaluatorTest, ResolveObjectSuccess) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -302,7 +302,7 @@ TEST_F(EvaluatorTest, ResolveStringTypeMismatch) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -327,7 +327,7 @@ TEST_F(EvaluatorTest, ResolveIntegerTypeMismatch) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -352,7 +352,7 @@ TEST_F(EvaluatorTest, ResolveDoubleTypeMismatch) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -371,7 +371,7 @@ class EvaluatorDefaultVariantTest
TEST_P(EvaluatorDefaultVariantTest, ResolveBooleanReturnsDefault) {
nlohmann::json flags_json =
nlohmann::json::parse(R"({"flags":)" + GetParam() + "}");
sync_->TriggerUpdate(flags_json);
EXPECT_TRUE(sync_->TriggerUpdate(flags_json).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -421,7 +421,7 @@ TEST_F(EvaluatorTest, ResolveBooleanDisabled) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -453,7 +453,7 @@ TEST_F(EvaluatorTest, ResolveStringTargetingSuccess) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

// Match targeting rule
openfeature::EvaluationContext ctx_blue =
Expand Down Expand Up @@ -504,7 +504,7 @@ TEST_F(EvaluatorTest, ResolveIntegerComplexTargeting) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx = openfeature::EvaluationContext::Builder()
.WithAttribute("env", "prod")
Expand Down Expand Up @@ -538,7 +538,7 @@ TEST_F(EvaluatorTest, ResolveObjectNestedStructure) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand Down Expand Up @@ -587,7 +587,7 @@ TEST_F(EvaluatorTest, ResolveBooleanFlagdSpecialVars) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx =
openfeature::EvaluationContext::Builder().build();
Expand All @@ -612,7 +612,7 @@ TEST_F(EvaluatorTest, ResolveBooleanTypeMismatchInTargeting) {
}
})");

sync_->TriggerUpdate(flags);
EXPECT_TRUE(sync_->TriggerUpdate(flags).ok());

openfeature::EvaluationContext ctx = openfeature::EvaluationContext::Builder()
.WithAttribute("color", "blue")
Expand Down
16 changes: 9 additions & 7 deletions providers/flagd/tests/smoke/openfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class MockSync : public flagd::FlagSync {
}
absl::Status Shutdown() override { return absl::OkStatus(); }

void SetFlags(const nlohmann::json& flags) { this->UpdateFlags(flags); }
absl::Status SetFlags(const nlohmann::json& flags) {
return this->UpdateFlags(flags);
}
Comment thread
m-olko marked this conversation as resolved.
};

class FlagdOpenFeatureTest : public ::testing::Test {
Expand Down Expand Up @@ -54,7 +56,7 @@ TEST_F(FlagdOpenFeatureTest, BooleanEvaluation) {
}
}
})");
sync_->SetFlags(flags);
EXPECT_TRUE(sync_->SetFlags(flags).ok());

EXPECT_TRUE(client_->GetBooleanValue("bool-flag", false));
EXPECT_FALSE(client_->GetBooleanValue("non-existent", false));
Expand All @@ -73,7 +75,7 @@ TEST_F(FlagdOpenFeatureTest, StringEvaluation) {
}
}
})");
sync_->SetFlags(flags);
EXPECT_TRUE(sync_->SetFlags(flags).ok());

EXPECT_EQ(client_->GetStringValue("string-flag", "default"), "value2");
}
Expand All @@ -91,7 +93,7 @@ TEST_F(FlagdOpenFeatureTest, IntegerEvaluation) {
}
}
})");
sync_->SetFlags(flags);
EXPECT_TRUE(sync_->SetFlags(flags).ok());

EXPECT_EQ(client_->GetIntegerValue("int-flag", 0), 1);
}
Expand All @@ -109,7 +111,7 @@ TEST_F(FlagdOpenFeatureTest, DoubleEvaluation) {
}
}
})");
sync_->SetFlags(flags);
EXPECT_TRUE(sync_->SetFlags(flags).ok());

EXPECT_DOUBLE_EQ(client_->GetDoubleValue("double-flag", 0.0), 2.2);
}
Expand All @@ -128,7 +130,7 @@ TEST_F(FlagdOpenFeatureTest, ObjectEvaluation) {
}
}
})");
sync_->SetFlags(flags);
EXPECT_TRUE(sync_->SetFlags(flags).ok());

openfeature::Value val =
client_->GetObjectValue("obj-flag", openfeature::Value());
Expand Down Expand Up @@ -159,7 +161,7 @@ TEST_F(FlagdOpenFeatureTest, EvaluationContextTargeting) {
}
}
})");
sync_->SetFlags(flags);
EXPECT_TRUE(sync_->SetFlags(flags).ok());

// Without context, should return defaultVariant "red"
EXPECT_EQ(client_->GetStringValue("targeting-flag", "default"), "red-value");
Expand Down
12 changes: 6 additions & 6 deletions providers/flagd/tests/smoke/sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ class MockSync : public flagd::FlagSync {
(override));
MOCK_METHOD(absl::Status, Shutdown, (), (override));

void TriggerUpdate(const nlohmann::json& new_json) {
this->UpdateFlags(new_json);
absl::Status TriggerUpdate(const nlohmann::json& new_json) {
return this->UpdateFlags(new_json);
}
Comment thread
m-olko marked this conversation as resolved.
};

Expand Down Expand Up @@ -55,7 +55,7 @@ TEST_F(FlagSyncTest, HelperMethodsUpdateAndRetrieveFlags) {
}
})"_json;

sync_.TriggerUpdate(expected_flags);
EXPECT_TRUE(sync_.TriggerUpdate(expected_flags).ok());

result_ptr = sync_.GetFlags();

Expand All @@ -82,7 +82,7 @@ TEST_F(FlagSyncTest, ThreadSafetyReadersAndWriters) {
const int k_iterations = 5000;
std::atomic<bool> start_flag{false};

auto writer_func = [&]() {
auto writer_func = [&] {
while (!start_flag.load());

for (int i = 0; i < k_iterations; ++i) {
Expand All @@ -99,11 +99,11 @@ TEST_F(FlagSyncTest, ThreadSafetyReadersAndWriters) {
"metadata": {}
})"_json;
update["flags"]["myFlag"]["variants"]["iteration"] = i;
sync_.TriggerUpdate(update);
EXPECT_TRUE(sync_.TriggerUpdate(update).ok());
}
};

auto reader_func = [&]() {
auto reader_func = [&] {
while (!start_flag.load());

for (int i = 0; i < k_iterations; ++i) {
Expand Down
Loading