...

Source file src/github.com/launchdarkly/go-server-sdk-evaluation/v2/interfaces.go

Documentation: github.com/launchdarkly/go-server-sdk-evaluation/v2

     1  package evaluation
     2  
     3  import (
     4  	"github.com/launchdarkly/go-server-sdk-evaluation/v2/ldmodel"
     5  
     6  	"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
     7  	"github.com/launchdarkly/go-sdk-common/v3/ldreason"
     8  	"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
     9  )
    10  
    11  // Evaluator is the engine for evaluating feature flags.
    12  type Evaluator interface {
    13  	// Evaluate evaluates a feature flag for the specified context.
    14  	//
    15  	// The flag is passed by reference only for efficiency; the evaluator will never modify any flag
    16  	// properties. Passing a nil flag will result in a panic.
    17  	//
    18  	// The evaluator does not know anything about analytics events; generating any appropriate analytics
    19  	// events is the responsibility of the caller, who can also provide a callback in prerequisiteFlagEventRecorder
    20  	// to be notified if any additional evaluations were done due to prerequisites. The prerequisiteFlagEventRecorder
    21  	// parameter can be nil if you do not need to track prerequisite evaluations.
    22  	Evaluate(
    23  		flag *ldmodel.FeatureFlag,
    24  		context ldcontext.Context,
    25  		prerequisiteFlagEventRecorder PrerequisiteFlagEventRecorder,
    26  	) Result
    27  }
    28  
    29  // PrerequisiteFlagEventRecorder is a function that Evaluator.Evaluate() will call to record the
    30  // result of a prerequisite flag evaluation.
    31  type PrerequisiteFlagEventRecorder func(PrerequisiteFlagEvent)
    32  
    33  // PrerequisiteFlagEvent is the parameter data passed to PrerequisiteFlagEventRecorder.
    34  type PrerequisiteFlagEvent struct {
    35  	// TargetFlagKey is the key of the feature flag that had a prerequisite.
    36  	TargetFlagKey string
    37  	// Context is the context that the flag was evaluated for. We pass this back to the caller, even though the caller
    38  	// already passed it to us in the Evaluate parameters, so that the caller can provide a stateless function for
    39  	// PrerequisiteFlagEventRecorder rather than a closure (since closures are less efficient).
    40  	Context ldcontext.Context
    41  	// PrerequisiteFlag is the full configuration of the prerequisite flag. We need to pass the full flag here rather
    42  	// than just the key because the flag's properties (such as TrackEvents) can affect how events are generated.
    43  	// This is passed by reference for efficiency only, and will never be nil; the PrerequisiteFlagEventRecorder
    44  	// must not modify the flag's properties.
    45  	PrerequisiteFlag *ldmodel.FeatureFlag
    46  	// PrerequisiteResult is the result of evaluating the prerequisite flag.
    47  	PrerequisiteResult Result
    48  }
    49  
    50  // DataProvider is an abstraction for querying feature flags and user segments from a data store.
    51  // The caller provides an implementation of this interface to NewEvaluator.
    52  //
    53  // Flags and segments are returned by reference for efficiency only (on the assumption that the
    54  // caller already has these objects in memory); the evaluator will never modify their properties.
    55  type DataProvider interface {
    56  	// GetFeatureFlag attempts to retrieve a feature flag from the data store by key.
    57  	//
    58  	// The evaluator calls this method if a flag contains a prerequisite condition referencing
    59  	// another flag.
    60  	//
    61  	// The method returns nil if the flag was not found. The DataProvider should treat any deleted
    62  	// flag as "not found" even if the data store contains a deleted flag placeholder for it.
    63  	GetFeatureFlag(key string) *ldmodel.FeatureFlag
    64  	// GetSegment attempts to retrieve a user segment from the data store by key.
    65  	//
    66  	// The evaluator calls this method if a clause in a flag rule uses the OperatorSegmentMatch
    67  	// test.
    68  	//
    69  	// The method returns nil if the segment was not found. The DataProvider should treat any deleted
    70  	// segment as "not found" even if the data store contains a deleted segment placeholder for it.
    71  	GetSegment(key string) *ldmodel.Segment
    72  }
    73  
    74  // BigSegmentProvider is an abstraction for querying membership in big segments. The caller
    75  // provides an implementation of this interface to NewEvaluatorWithBigSegments.
    76  type BigSegmentProvider interface {
    77  	// GetMembership queries a snapshot of the current segment state for a specific context
    78  	// key.
    79  	//
    80  	// The underlying big segment store implementation will use a hash of the context key, rather
    81  	// than the raw key. But computing the hash is the responsibility of the BigSegmentProvider
    82  	// implementation rather than the evaluator, because there may already have a cached result for
    83  	// that user, and we don't want to have to compute a hash repeatedly just to query a cache.
    84  	//
    85  	// Any given big segment is specific to one context kind, so we do not specify a context kind
    86  	// here; it is OK for the membership results to include different context kinds for the same
    87  	// key. That is, if for instance the context {kind: "user", key: "x"} is included in big segment
    88  	// S1, and the context {kind: "org", key: "x"} is included in big segment S2, then the query
    89  	// result for key "x" will show that it is included in both S1 and S2; even though those "x"
    90  	// keys are really for two unrelated context kinds, we will always know which kind we mean if
    91  	// we are specifically checking either S1 or S2, because S1 is defined as only applying to the
    92  	// "user" kind and S2 is defined as only applying to the "org" kind.
    93  	//
    94  	// If the returned BigSegmentMembership is nil, it is treated the same as an implementation
    95  	// whose CheckMembership method always returns an empty value.
    96  	GetMembership(
    97  		contextKey string,
    98  	) (BigSegmentMembership, ldreason.BigSegmentsStatus)
    99  }
   100  
   101  // BigSegmentMembership is the return type of BigSegmentProvider.GetContextMembership(). It is
   102  // associated with a single context kind and context key, and provides the ability to check whether
   103  // that context is included in or excluded from any number of big segments.
   104  //
   105  // This is an immutable snapshot of the state for this context at the time GetBigSegmentMembership
   106  // was called. Calling CheckMembership should not cause the state to be queried again. The object
   107  // should be safe for concurrent access by multiple goroutines.
   108  //
   109  // This interface also exists in go-server-sdk because it is exposed as part of the public SDK API;
   110  // users can write their own implementations of SDK components, but we do not want application code
   111  // to reference go-server-sdk-evaluation symbols directly as part of that, because this library is
   112  // versioned separately from the SDK. Currently the two interfaces are identical, but it might be
   113  // that the go-server-sdk-evaluation version would diverge from the go-server-sdk version due to
   114  // some internal requirements that aren't relevant to users, in which case go-server-sdk would be
   115  // responsible for bridging the difference.
   116  type BigSegmentMembership interface {
   117  	// CheckMembership tests whether the user is explicitly included or explicitly excluded in the
   118  	// specified segment, or neither. The segment is identified by a segmentRef which is not the
   119  	// same as the segment key-- it includes the key but also versioning information that the SDK
   120  	// will provide. The store implementation should not be concerned with the format of this.
   121  	//
   122  	// If the user is explicitly included (regardless of whether the user is also explicitly
   123  	// excluded or not-- that is, inclusion takes priority over exclusion), the method returns an
   124  	// OptionalBool with a true value.
   125  	//
   126  	// If the user is explicitly excluded, and is not explicitly included, the method returns an
   127  	// OptionalBool with a false value.
   128  	//
   129  	// If the user's status in the segment is undefined, the method returns OptionalBool{} with no
   130  	// value (so calling IsDefined() on it will return false).
   131  	CheckMembership(segmentRef string) ldvalue.OptionalBool
   132  }
   133  

View as plain text