Module: Philiprehberger::FeatureFlag
- Extended by:
- Dependencies, Groups, Metrics, Scheduling, Targeting
- Defined in:
- lib/philiprehberger/feature_flag.rb,
lib/philiprehberger/feature_flag/groups.rb,
lib/philiprehberger/feature_flag/metrics.rb,
lib/philiprehberger/feature_flag/rollout.rb,
lib/philiprehberger/feature_flag/version.rb,
lib/philiprehberger/feature_flag/targeting.rb,
lib/philiprehberger/feature_flag/scheduling.rb,
lib/philiprehberger/feature_flag/dependencies.rb,
lib/philiprehberger/feature_flag/configuration.rb,
lib/philiprehberger/feature_flag/backends/env_backend.rb,
lib/philiprehberger/feature_flag/backends/yaml_backend.rb,
lib/philiprehberger/feature_flag/backends/memory_backend.rb
Defined Under Namespace
Modules: Backends, Dependencies, Groups, Metrics, Rollout, Scheduling, Targeting Classes: Configuration
Constant Summary collapse
- VERSION =
'0.4.0'
Class Method Summary collapse
- .configuration ⇒ Object
-
.configure {|config| ... } ⇒ void
Configure the feature flag system.
-
.enabled?(flag, user_id: nil, user: nil, context: {}) ⇒ Boolean, Object
Check whether
flagis enabled. -
.flag_names ⇒ Array<Symbol>
Return the sorted, deduplicated union of every flag name known to the configured backend and the registered dependency, schedule, targeting, and group subsystems.
- .reload! ⇒ Object
- .reset! ⇒ Object
-
.variant(flag, user_id:, context: {}) ⇒ String?
Return the A/B variant for
user_idonflag. - .with(flag, value) ⇒ Object
Methods included from Groups
disable_group, enable_group, group, group_flags, reset_groups!
Methods included from Targeting
disable_for, enable_for, reset_targets!, targeted?, targeted_contexts, targeted_users
Methods included from Metrics
metrics, record_metric, reset_metrics!
Methods included from Scheduling
reset_schedules!, schedule, schedule_for, scheduled_active?
Methods included from Dependencies
dependencies_met?, dependency_for, depends_on, reset_dependencies!
Class Method Details
.configuration ⇒ Object
24 25 26 |
# File 'lib/philiprehberger/feature_flag.rb', line 24 def configuration @configuration ||= Configuration.new end |
.configure {|config| ... } ⇒ void
This method returns an undefined value.
Configure the feature flag system. Yields the shared Configuration instance so callers can pick a backend or mutate settings.
34 35 36 |
# File 'lib/philiprehberger/feature_flag.rb', line 34 def configure yield(configuration) end |
.enabled?(flag, user_id: nil, user: nil, context: {}) ⇒ Boolean, Object
Check whether flag is enabled. The lookup honors (in order): in-flight overrides from with, dependency gates, scheduling windows, user targeting, and finally the backend value — which may be a boolean, a percentage rollout, or any truthy value.
51 52 53 54 55 56 57 |
# File 'lib/philiprehberger/feature_flag.rb', line 51 def enabled?(flag, user_id: nil, user: nil, context: {}) return @overrides[flag.to_s] if overridden?(flag) result = evaluate_flag(flag, user_id, user, context) record_metric(flag, result) result end |
.flag_names ⇒ Array<Symbol>
Return the sorted, deduplicated union of every flag name known to the configured backend and the registered dependency, schedule, targeting, and group subsystems.
Backends that do not expose their flag names (for example, opaque remote backends without an all accessor) are skipped silently.
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/philiprehberger/feature_flag.rb', line 109 def flag_names names = [] names.concat(backend_flag_names) names.concat(Array(@dependencies&.keys)) names.concat(Array(@dependencies&.values)) names.concat(Array(@schedules&.keys)) names.concat(Array(@targets&.keys)) names.concat(Array(@groups&.values).flatten) names.map(&:to_sym).uniq.sort end |
.reload! ⇒ Object
97 98 99 |
# File 'lib/philiprehberger/feature_flag.rb', line 97 def reload! configuration.backend.reload! end |
.reset! ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/philiprehberger/feature_flag.rb', line 120 def reset! @configuration = nil @overrides = nil reset_dependencies! reset_schedules! reset_metrics! reset_targets! reset_groups! end |
.variant(flag, user_id:, context: {}) ⇒ String?
Return the A/B variant for user_id on flag. Variants are stored as { ‘variants’ => […] } on the backend and selected deterministically from the user id (optionally combined with context when the flag declares rollout_by).
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/philiprehberger/feature_flag.rb', line 70 def variant(flag, user_id:, context: {}) value = configuration.backend.get(flag) return nil unless variant_value?(value) variants = value['variants'] rollout_by = Array(value['rollout_by']).map(&:to_sym) rollout_by = [:user_id] if rollout_by.empty? key = Rollout.bucket_key(user_id, context, rollout_by) || user_id.to_s bucket = Zlib.crc32("#{flag}:#{key}") % variants.size variants[bucket] end |
.with(flag, value) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/philiprehberger/feature_flag.rb', line 82 def with(flag, value) @overrides ||= {} key = flag.to_s had_previous = @overrides.key?(key) previous = @overrides[key] @overrides[key] = value yield ensure if had_previous @overrides[key] = previous else @overrides&.delete(key) end end |