Module: Feat::Eval
- Defined in:
- lib/feat/eval.rb
Class Method Summary collapse
-
.call(flag_key:, default_value:, ctx:, datafile:) ⇒ Object
Run the precedence pipeline:.
- .match_rule?(rule, ctx, datafile) ⇒ Boolean
- .pick_rollout(flag, rollout, ctx) ⇒ Object
- .resolve_variation(flag, variation_id, reason, default_value) ⇒ Object
Class Method Details
.call(flag_key:, default_value:, ctx:, datafile:) ⇒ Object
Run the precedence pipeline:
1. archived flag -> off variation DISABLED
2. !isEnabled -> off variation DISABLED
3. individual target -> target variation TARGETING_MATCH
4. first matching rule -> rule variation/rollout TARGETING_MATCH / SPLIT
5. default -> default variation/rollout FALLTHROUGH / SPLIT
6. nothing matched -> off variation DEFAULT
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 |
# File 'lib/feat/eval.rb', line 31 def call(flag_key:, default_value:, ctx:, datafile:) flag = datafile.flags[flag_key] if flag.nil? return EvaluationResult.new( value: default_value, reason: Reason::ERROR, error_message: "flag could not be evaluated" ) end if flag.archived || !flag.isEnabled return resolve_variation(flag, flag.offVariationId, Reason::DISABLED, default_value) end flag.targets.each do |target| ctx_key = ContextResolver.read_context_key(ctx, target.contextKindKey) if !ctx_key.nil? && ctx_key == target.contextKey return resolve_variation(flag, target.variationId, Reason::TARGETING_MATCH, default_value) end end flag.rules.each do |rule| next unless match_rule?(rule, ctx, datafile) if !rule.variationId.nil? return resolve_variation(flag, rule.variationId, Reason::TARGETING_MATCH, default_value) end if !rule.rollout.nil? picked = pick_rollout(flag, rule.rollout, ctx) return resolve_variation(flag, picked, Reason::SPLIT, default_value) unless picked.nil? end end if !flag.defaultVariationId.nil? return resolve_variation(flag, flag.defaultVariationId, Reason::FALLTHROUGH, default_value) end if !flag.defaultRollout.nil? picked = pick_rollout(flag, flag.defaultRollout, ctx) return resolve_variation(flag, picked, Reason::SPLIT, default_value) unless picked.nil? end resolve_variation(flag, flag.offVariationId, Reason::DEFAULT, default_value) end |
.match_rule?(rule, ctx, datafile) ⇒ Boolean
74 75 76 77 78 79 80 81 82 |
# File 'lib/feat/eval.rb', line 74 def match_rule?(rule, ctx, datafile) return false if rule.groups.empty? rule.groups.any? do |group| next false if group.conditions.empty? group.conditions.all? { |cond| Segments.match_condition(cond, ctx, datafile) } end end |
.pick_rollout(flag, rollout, ctx) ⇒ Object
84 85 86 87 88 89 90 |
# File 'lib/feat/eval.rb', line 84 def pick_rollout(flag, rollout, ctx) ctx_key = ContextResolver.read_context_key(ctx, rollout.bucketingContextKindKey) return nil if ctx_key.nil? b = Bucketing.bucket(salt: flag.salt, flag_key: flag.key, context_key: ctx_key) Bucketing.pick_by_weight(b, rollout.variations) end |
.resolve_variation(flag, variation_id, reason, default_value) ⇒ Object
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/feat/eval.rb', line 92 def resolve_variation(flag, variation_id, reason, default_value) v = flag.variations.find { |x| x.id == variation_id } if v.nil? return EvaluationResult.new( value: default_value, reason: Reason::ERROR, error_message: "flag could not be evaluated" ) end EvaluationResult.new(value: v.value, variation_id: variation_id, reason: reason) end |