Class: LaunchDarkly::Impl::Evaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/ldclient-rb/impl/evaluator.rb

Overview

Encapsulates the feature flag evaluation logic. The Evaluator has no knowledge of the rest of the SDK environment; if it needs to retrieve flags or segments that are referenced by a flag, it does so through a simple function that is provided in the constructor. It also produces feature requests as appropriate for any referenced prerequisite flags, but does not send them.

Since:

  • 5.5.0

Defined Under Namespace

Classes: EvalResult

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(get_flag, get_segment, get_big_segments_membership, logger) ⇒ Evaluator

A single Evaluator is instantiated for each client instance.

Parameters:

  • get_flag (Function)

    called if the Evaluator needs to query a different flag from the one that it is currently evaluating (i.e. a prerequisite flag); takes a single parameter, the flag key, and returns the flag data - or nil if the flag is unknown or deleted

  • get_segment (Function)

    similar to ‘get_flag`, but is used to query a context segment.

  • logger (Logger)

    the client’s logger

Since:

  • 5.5.0



112
113
114
115
116
117
# File 'lib/ldclient-rb/impl/evaluator.rb', line 112

def initialize(get_flag, get_segment, get_big_segments_membership, logger)
  @get_flag = get_flag
  @get_segment = get_segment
  @get_big_segments_membership = get_big_segments_membership
  @logger = logger
end

Class Method Details

.error_result(errorKind, value = nil) ⇒ Object

Helper function used internally to construct an EvaluationDetail for an error result.

Since:

  • 5.5.0



136
137
138
# File 'lib/ldclient-rb/impl/evaluator.rb', line 136

def self.error_result(errorKind, value = nil)
  EvaluationDetail.new(value, nil, EvaluationReason.error(errorKind))
end

.make_big_segment_ref(segment) ⇒ Object

Parameters:

Since:

  • 5.5.0



175
176
177
178
179
180
# File 'lib/ldclient-rb/impl/evaluator.rb', line 175

def self.make_big_segment_ref(segment)  # method is visible for testing
  # The format of Big Segment references is independent of what store implementation is being
  # used; the store implementation receives only this string and does not know the details of
  # the data model. The Relay Proxy will use the same format when writing to the store.
  "#{segment.key}.g#{segment.generation}"
end

Instance Method Details

#evaluate(flag, context) ⇒ Array<EvalResult, EvaluatorState>

The client’s entry point for evaluating a flag. The returned ‘EvalResult` contains the evaluation result and any events that were generated for prerequisite flags; its `value` will be `nil` if the flag returns the default value. Error conditions produce a result with a nil value and an error reason, not an exception.

inspecting the evaluation process

Parameters:

Returns:

Since:

  • 5.5.0



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/ldclient-rb/impl/evaluator.rb', line 148

def evaluate(flag, context)
  state = EvaluatorState.new(flag)

  result = EvalResult.new
  begin
    detail = eval_internal(flag, context, result, state)
  rescue EvaluationException => exn
    LaunchDarkly::Util.log_exception(@logger, "Unexpected error when evaluating flag #{flag.key}", exn)
    result.detail = EvaluationDetail.new(nil, nil, EvaluationReason::error(exn.error_kind))
    return result, state
  rescue => exn
    LaunchDarkly::Util.log_exception(@logger, "Unexpected error when evaluating flag #{flag.key}", exn)
    result.detail = EvaluationDetail.new(nil, nil, EvaluationReason::error(EvaluationReason::ERROR_EXCEPTION))
    return result, state
  end

  unless result.big_segments_status.nil?
    # If big_segments_status is non-nil at the end of the evaluation, it means a query was done at
    # some point and we will want to include the status in the evaluation reason.
    detail = EvaluationDetail.new(detail.value, detail.variation_index,
      detail.reason.with_big_segments_status(result.big_segments_status))
  end
  result.detail = detail
  [result, state]
end