1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
use async_trait::async_trait;
use crate::{EvaluationContext, EvaluationResult, StructValue};
use super::ResolutionDetails;
// ============================================================
// FeatureProvider
// ============================================================
/// This trait defines interfaces that Provider Authors can use to abstract a particular flag
/// management system, thus enabling the use of the evaluation API by Application Authors.
///
/// Providers are the "translator" between the flag evaluation calls made in application code, and
/// the flag management system that stores flags and in some cases evaluates flags. At a minimum,
/// providers should implement some basic evaluation methods which return flag values of the
/// expected type. In addition, providers may transform the evaluation context appropriately in
/// order to be used in dynamic evaluation of their associated flag management system, provide
/// insight into why evaluation proceeded the way it did, and expose configuration options for
/// their associated flag management system. Hypothetical provider implementations might wrap a
/// vendor SDK, embed an REST client, or read flags from a local file.
///
/// See the [spec](https://openfeature.dev/specification/sections/providers).
#[cfg_attr(feature = "test-util", mockall::automock)]
#[async_trait]
pub trait FeatureProvider: Send + Sync + 'static {
/// The provider MAY define an initialize function which accepts the global evaluation
/// context as an argument and performs initialization logic relevant to the provider.
///
/// Note the following rules:
/// * The provider MUST set its status field/accessor to READY if its initialize function
/// terminates normally.
/// * The provider MUST set its status field to ERROR if its initialize function terminates
/// abnormally.
/// * The provider SHOULD indicate an error if flag resolution is attempted before the provider
/// is ready.
#[allow(unused_variables)]
async fn initialize(&mut self, context: &EvaluationContext) {}
/// The provider MAY define a status field/accessor which indicates the readiness of the
/// provider, with possible values NOT_READY, READY, or ERROR.
///
/// Providers without this field can be assumed to be ready immediately.
fn status(&self) -> ProviderStatus {
ProviderStatus::Ready
}
/// The provider interface MUST define a metadata member or accessor, containing a name field
/// or accessor of type string, which identifies the provider implementation.
fn metadata(&self) -> &ProviderMetadata;
/// Resolve given `flag_key` as a bool value.
async fn resolve_bool_value(
&self,
flag_key: &str,
evaluation_context: &EvaluationContext,
) -> EvaluationResult<ResolutionDetails<bool>>;
/// Resolve given `flag_key` as an i64 value.
async fn resolve_int_value(
&self,
flag_key: &str,
evaluation_context: &EvaluationContext,
) -> EvaluationResult<ResolutionDetails<i64>>;
/// Resolve given `flag_key` as a f64 value.
async fn resolve_float_value(
&self,
flag_key: &str,
evaluation_context: &EvaluationContext,
) -> EvaluationResult<ResolutionDetails<f64>>;
/// Resolve given `flag_key` as a string value.
async fn resolve_string_value(
&self,
flag_key: &str,
evaluation_context: &EvaluationContext,
) -> EvaluationResult<ResolutionDetails<String>>;
/// Resolve given `flag_key` as a struct value.
async fn resolve_struct_value(
&self,
flag_key: &str,
evaluation_context: &EvaluationContext,
) -> EvaluationResult<ResolutionDetails<StructValue>>;
}
// ============================================================
// ProviderMetadata
// ============================================================
/// The metadata of a feature provider.
#[derive(Clone, Default, Debug)]
pub struct ProviderMetadata {
/// The name of provider.
pub name: String,
}
impl ProviderMetadata {
/// Create a new instance out of a string.
pub fn new<S: Into<String>>(name: S) -> Self {
Self { name: name.into() }
}
}
//
// ============================================================
// ProviderStatus
// ============================================================
/// The status of a feature provider.
#[derive(Default, PartialEq, Eq, Debug)]
pub enum ProviderStatus {
/// The provider has not been initialized.
#[default]
NotReady,
/// The provider has been initialized, and is able to reliably resolve flag values.
Ready,
/// The provider is initialized but is not able to reliably resolve flag values.
Error,
/// The provider's cached state is no longer valid and may not be up-to-date with the source of
/// truth.
STALE,
}