Skip to content
Closed
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
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7.4.1
48 changes: 48 additions & 0 deletions openfeature/BUILD
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
load("@rules_cc//cc:defs.bzl", "cc_library")

package(
default_visibility = ["//visibility:public"],
)

cc_library(
name = "client_api",
srcs = ["client_api.cpp"],
hdrs = ["client_api.h"],
include_prefix = "openfeature",
deps = [
":client",
":evaluation_context",
":features",
":flag_metadata",
":global_context_manager",
":metadata",
":provider",
":provider_repository",
":provider_status",
":reason",
":resolution_details",
],
)

cc_library(
name = "client",
hdrs = ["client.h"],
Expand Down Expand Up @@ -55,6 +77,16 @@ cc_library(
include_prefix = "openfeature",
)

cc_library(
name = "global_context_manager",
srcs = ["global_context_manager.cpp"],
hdrs = ["global_context_manager.h"],
include_prefix = "openfeature",
deps = [
":evaluation_context",
],
)

cc_library(
name = "metadata",
hdrs = ["metadata.h"],
Expand All @@ -73,6 +105,22 @@ cc_library(
":resolution_details",
],
)
cc_library(
name = "openfeature_api",
srcs = ["openfeature_api.cpp"],
hdrs = ["openfeature_api.h"],
include_prefix = "openfeature",
deps = [
":client",
":client_api",
":evaluation_context",
":global_context_manager",
":metadata",
":openfeature",
":provider",
":provider_repository",
],
)

cc_library(
name = "openfeature",
Expand Down
71 changes: 71 additions & 0 deletions openfeature/client_api.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "client_api.h"

#include <utility>

#include "openfeature/flag_metadata.h"
#include "openfeature/global_context_manager.h"
#include "openfeature/reason.h"

namespace openfeature {

ClientAPI::ClientAPI(ProviderRepository& repository, std::string_view domain)
: provider_repository_(repository), domain_(domain) {}

Metadata ClientAPI::GetMetadata() { return Metadata{domain_}; }

EvaluationContext ClientAPI::GetEvaluationContext() {
std::lock_guard<std::mutex> lock(context_mutex_);
return evaluation_context_;
}

void ClientAPI::SetEvaluationContext(const EvaluationContext& ctx) {
std::lock_guard<std::mutex> lock(context_mutex_);
evaluation_context_ = ctx;
}

ProviderStatus ClientAPI::GetProviderStatus() {
return provider_repository_.GetProviderStatus(domain_);
}

bool ClientAPI::GetBooleanValue(std::string_view flag_key, bool default_value) {
return EvaluateBooleanFlag(flag_key, default_value, std::nullopt)->GetValue();
}

bool ClientAPI::GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationContext& ctx) {
return EvaluateBooleanFlag(flag_key, default_value, ctx)->GetValue();
}

std::unique_ptr<BoolResolutionDetails> ClientAPI::EvaluateBooleanFlag(
std::string_view flag_key, bool default_value,
const std::optional<EvaluationContext>& ctx) {
if (GetProviderStatus() != ProviderStatus::kReady) {
return std::make_unique<BoolResolutionDetails>(
default_value, Reason::kError, std::nullopt, FlagMetadata(),
ErrorCode::kProviderNotReady, "Provider is not ready");
}

std::shared_ptr<FeatureProvider> provider =
provider_repository_.GetProvider(domain_);
if (!provider) {
return std::make_unique<BoolResolutionDetails>(
default_value, Reason::kError, std::nullopt, FlagMetadata(),
ErrorCode::kProviderFatal, "Provider not found for domain");
}

EvaluationContext merged_context = MergeContexts(ctx);
return provider->GetBooleanEvaluation(flag_key, default_value,
merged_context);
}

EvaluationContext ClientAPI::MergeContexts(
const std::optional<EvaluationContext>& invocation_ctx) {
// TODO: Add context merging logic after EvaluationContext is implemented.

if (invocation_ctx) {
return *invocation_ctx;
}
return GetEvaluationContext();
}
Comment thread
NeaguGeorgiana23 marked this conversation as resolved.

} // namespace openfeature
69 changes: 69 additions & 0 deletions openfeature/client_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#ifndef CPP_SDK_INCLUDE_OPENFEATURE_CLIENT_API_H_
#define CPP_SDK_INCLUDE_OPENFEATURE_CLIENT_API_H_

#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>

#include "openfeature/client.h"
#include "openfeature/evaluation_context.h"
#include "openfeature/features.h"
#include "openfeature/global_context_manager.h"
#include "openfeature/metadata.h"
#include "openfeature/provider.h"
#include "openfeature/provider_repository.h"
#include "openfeature/provider_status.h"
#include "openfeature/resolution_details.h"

namespace openfeature {

// OpenFeature client implementation.
class ClientAPI : public Client {
public:
ClientAPI(ProviderRepository& repository, std::string_view domain);

~ClientAPI() override = default;

ClientAPI(const ClientAPI&) = delete;
ClientAPI& operator=(const ClientAPI&) = delete;

Metadata GetMetadata() override;

// Return an optional client-level evaluation context.
EvaluationContext GetEvaluationContext() override;

// Set the client-level evaluation context.
void SetEvaluationContext(const EvaluationContext& ctx) override;

// Returns the current status of the associated provider.
ProviderStatus GetProviderStatus() override;

bool GetBooleanValue(std::string_view flag_key, bool default_value) override;
bool GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationContext& ctx) override;

// TODO: Add methods to get and set Hooks.
// TODO: Add methods for flag evaluation for other types (e.g. string, int,
// float, object).
// TODO: Add methods for detailed flag evaluation.
// TODO: Overload method "GetBooleanValue" to accept "Evaluation Options".

private:
std::unique_ptr<BoolResolutionDetails> EvaluateBooleanFlag(
std::string_view flag_key, bool default_value,
const std::optional<EvaluationContext>& ctx);

EvaluationContext MergeContexts(
const std::optional<EvaluationContext>& invocation_ctx);

ProviderRepository& provider_repository_;
std::string domain_;
EvaluationContext evaluation_context_;
mutable std::mutex context_mutex_;
};

} // namespace openfeature

#endif // CPP_SDK_INCLUDE_OPENFEATURE_CLIENT_API_H_
23 changes: 23 additions & 0 deletions openfeature/global_context_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "openfeature/global_context_manager.h"

#include <mutex>

namespace openfeature {

GlobalContextManager& GlobalContextManager::GetInstance() {
static GlobalContextManager instance;
return instance;
}

void GlobalContextManager::SetGlobalEvaluationContext(
const EvaluationContext& ctx) {
std::unique_lock<std::shared_mutex> lock(context_mutex_);
global_evaluation_context_ = ctx;
}

EvaluationContext GlobalContextManager::GetGlobalEvaluationContext() const {
std::shared_lock<std::shared_mutex> lock(context_mutex_);
return global_evaluation_context_;
}

} // namespace openfeature
34 changes: 34 additions & 0 deletions openfeature/global_context_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef CPP_SDK_INCLUDE_OPENFEATURE_GLOBAL_CONTEXT_MANAGER_H_
#define CPP_SDK_INCLUDE_OPENFEATURE_GLOBAL_CONTEXT_MANAGER_H_

#include <memory>
#include <shared_mutex>

#include "openfeature/evaluation_context.h"

namespace openfeature {

// Manages the global Evaluation Context for the OpenFeature SDK.
// This data is static across the application (unless explicitly changed)
class GlobalContextManager {
public:
static GlobalContextManager& GetInstance();

GlobalContextManager(const GlobalContextManager&) = delete;
GlobalContextManager& operator=(const GlobalContextManager&) = delete;

// Updates the global evaluation context.
void SetGlobalEvaluationContext(const EvaluationContext& ctx);

// Retrieves the current global evaluation context.
EvaluationContext GetGlobalEvaluationContext() const;

private:
GlobalContextManager() = default;
EvaluationContext global_evaluation_context_;
mutable std::shared_mutex context_mutex_;
};

} // namespace openfeature

#endif // CPP_SDK_INCLUDE_OPENFEATURE_GLOBAL_CONTEXT_MANAGER_H_
26 changes: 10 additions & 16 deletions openfeature/openfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,15 @@ class OpenFeature {
virtual void SetProviderAndWait(
std::shared_ptr<FeatureProvider> provider) = 0;

// Sets the default provider and blocks until it initializes or a timeout
// occurs.
virtual void SetProviderAndWait(std::shared_ptr<FeatureProvider> provider,
std::chrono::milliseconds timeout) = 0;

// Sets a named provider and blocks until it successfully initializes.
virtual void SetProviderAndWait(
std::string_view domain, std::shared_ptr<FeatureProvider> provider) = 0;

// Sets a named provider and blocks until it initializes or a timeout occurs.
virtual void SetProviderAndWait(std::string_view domain,
std::shared_ptr<FeatureProvider> provider,
std::chrono::milliseconds timeout) = 0;

// If the domain is empty then GetProvider returns the default provider
// otherwise it returns the provider for the domain. If this domain has no
// provider bound, it returns the default provider.
virtual std::shared_ptr<FeatureProvider> GetProvider(
std::string_view domain = "") = 0;
std::string_view domain = "") const = 0;

virtual std::shared_ptr<Client> GetClient() = 0;

Expand All @@ -55,17 +45,21 @@ class OpenFeature {
// Sets the global evaluation context.
virtual void SetEvaluationContext(const EvaluationContext& ctx) = 0;

// Gets the global evaluation context
virtual EvaluationContext GetEvaluationContext(
std::shared_mutex& mutex, const EvaluationContext& ctx_src) = 0;
// Gets the global evaluation context.
virtual EvaluationContext GetEvaluationContext() const = 0;

// Gets the metadata for a provider bound to a specific domain.
virtual Metadata GetProviderMetadata(std::string_view domain = "") = 0;
virtual Metadata GetProviderMetadata(std::string_view domain = "") const = 0;

// Fetches the status of a provider for a domain. If the domain is not set or
// not found, it returns the default provider status.
virtual ProviderStatus GetProviderStatus(
std::string_view domain = "") const = 0;

// Shuts down all providers and resets the API to its initial state.
virtual void Shutdown() = 0;

// TODO: Add methods to add and get Hooks
// TODO: Add methods to add and get Hooks.
};

} // namespace openfeature
Expand Down
Loading