magick-feature-flags 0.9.18 → 0.9.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/magick/feature.rb +54 -42
- data/lib/magick/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a9bd8f59c8729764a5a1b9876b20bca16dce2670ed477ee64109eda02219f98
|
|
4
|
+
data.tar.gz: 566826dcca95d42a34fd5f95581e5dfd1c3d074a3260def10fda5bb3a68c5ce0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b37fb6089b687c08b31aad74d24f43c90d65134c9e68e0de2d521a6357f64d0f3778b8aafe60aca9f912f4610d73a42e4e6a2f96f156f66a8c5d154affa8d91
|
|
7
|
+
data.tar.gz: 267b78151d2017069f1a3e4836ed0016bbdc524ee9fb2d7ea15ec8148df9359604f9acf9dca886aa073fb289309c5f4f90ce39754d8da80d95794606b0a05087
|
data/lib/magick/feature.rb
CHANGED
|
@@ -22,26 +22,35 @@ module Magick
|
|
|
22
22
|
@dependencies = options[:dependencies] ? Array(options[:dependencies]) : []
|
|
23
23
|
@stored_value_initialized = false # Track if @stored_value has been explicitly set
|
|
24
24
|
|
|
25
|
+
# Performance optimizations: cache expensive checks
|
|
26
|
+
@_targeting_empty = true # Will be updated after load_from_adapter
|
|
27
|
+
@_rails_events_enabled = false # Cache Rails events availability (only enable in dev)
|
|
28
|
+
|
|
25
29
|
validate_type!
|
|
26
30
|
validate_default_value!
|
|
27
31
|
load_from_adapter
|
|
32
|
+
# Update targeting empty cache after loading
|
|
33
|
+
@_targeting_empty = @targeting.empty?
|
|
28
34
|
# Save description and display_name to adapter if they were provided and not already in adapter
|
|
29
35
|
save_metadata_if_new
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
def enabled?(context = {})
|
|
33
|
-
#
|
|
34
|
-
|
|
39
|
+
# Performance metrics: measure before the check (only if enabled)
|
|
40
|
+
perf_metrics = Magick.performance_metrics
|
|
41
|
+
start_time = perf_metrics ? Process.clock_gettime(Process::CLOCK_MONOTONIC) : nil
|
|
35
42
|
|
|
43
|
+
# Fast path: check enabled status
|
|
36
44
|
result = check_enabled(context)
|
|
37
45
|
|
|
38
|
-
if
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
# Record metrics if enabled (after the check to minimize overhead)
|
|
47
|
+
if perf_metrics
|
|
48
|
+
duration = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000 # milliseconds
|
|
49
|
+
perf_metrics.record(name, 'enabled?', duration, success: true)
|
|
41
50
|
end
|
|
42
51
|
|
|
43
|
-
# Rails 8+ events
|
|
44
|
-
if
|
|
52
|
+
# Rails 8+ events (only in development or when explicitly enabled)
|
|
53
|
+
if @_rails_events_enabled
|
|
45
54
|
if result
|
|
46
55
|
Magick::Rails::Events.feature_enabled(name, context: context)
|
|
47
56
|
else
|
|
@@ -49,21 +58,17 @@ module Magick
|
|
|
49
58
|
end
|
|
50
59
|
end
|
|
51
60
|
|
|
52
|
-
# Warn if deprecated
|
|
53
|
-
if status == :deprecated && result && !context[:allow_deprecated]
|
|
54
|
-
warn "DEPRECATED: Feature '#{name}' is deprecated and will be removed."
|
|
55
|
-
|
|
56
|
-
# Rails 8+ event for deprecation warning
|
|
57
|
-
if defined?(Magick::Rails::Events) && Magick::Rails::Events.rails8?
|
|
58
|
-
Magick::Rails::Events.deprecated_warning(name)
|
|
59
|
-
end
|
|
61
|
+
# Warn if deprecated (only if enabled)
|
|
62
|
+
if status == :deprecated && result && !context[:allow_deprecated] && Magick.warn_on_deprecated
|
|
63
|
+
warn "DEPRECATED: Feature '#{name}' is deprecated and will be removed."
|
|
64
|
+
Magick::Rails::Events.deprecated_warning(name) if @_rails_events_enabled
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
result
|
|
63
68
|
rescue StandardError => e
|
|
64
|
-
if
|
|
65
|
-
duration = (
|
|
66
|
-
|
|
69
|
+
if perf_metrics
|
|
70
|
+
duration = start_time ? (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time) * 1000 : 0.0
|
|
71
|
+
perf_metrics.record(name, 'enabled?', duration, success: false)
|
|
67
72
|
end
|
|
68
73
|
# Return false on any error (fail-safe)
|
|
69
74
|
warn "Magick: Error checking feature '#{name}': #{e.message}" if defined?(Rails) && Rails.env.development?
|
|
@@ -71,28 +76,28 @@ module Magick
|
|
|
71
76
|
end
|
|
72
77
|
|
|
73
78
|
def check_enabled(context = {})
|
|
79
|
+
# Fast path: check status first
|
|
74
80
|
return false if status == :inactive
|
|
75
81
|
return false if status == :deprecated && !context[:allow_deprecated]
|
|
76
82
|
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# Check date/time range targeting
|
|
83
|
-
return false if targeting[:date_range] && !date_range_active?(targeting[:date_range])
|
|
83
|
+
# Fast path: skip targeting checks if targeting is empty (most common case)
|
|
84
|
+
unless @_targeting_empty
|
|
85
|
+
# Check date/time range targeting
|
|
86
|
+
return false if targeting[:date_range] && !date_range_active?(targeting[:date_range])
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
# Check IP address targeting
|
|
89
|
+
return false if targeting[:ip_address] && context[:ip_address] && !ip_address_matches?(context[:ip_address])
|
|
87
90
|
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
# Check custom attributes
|
|
92
|
+
return false if targeting[:custom_attributes] && !custom_attributes_match?(context,
|
|
93
|
+
targeting[:custom_attributes])
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
# Check complex conditions
|
|
96
|
+
return false if targeting[:complex_conditions] && !complex_conditions_match?(context,
|
|
97
|
+
targeting[:complex_conditions])
|
|
94
98
|
end
|
|
95
99
|
|
|
100
|
+
# Get value and check based on type
|
|
96
101
|
value = get_value(context)
|
|
97
102
|
case type
|
|
98
103
|
when :boolean
|
|
@@ -131,19 +136,21 @@ module Magick
|
|
|
131
136
|
end
|
|
132
137
|
|
|
133
138
|
def get_value(context = {})
|
|
134
|
-
#
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
# Fast path: check targeting rules first (only if targeting exists)
|
|
140
|
+
unless @_targeting_empty
|
|
141
|
+
targeting_result = check_targeting(context)
|
|
142
|
+
return targeting_result unless targeting_result.nil?
|
|
143
|
+
end
|
|
137
144
|
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
# We track this by checking if @stored_value_initialized flag is set
|
|
141
|
-
return @stored_value if defined?(@stored_value_initialized) && @stored_value_initialized
|
|
145
|
+
# Fast path: use cached value if initialized (avoid adapter calls)
|
|
146
|
+
return @stored_value if @stored_value_initialized
|
|
142
147
|
|
|
143
148
|
# Load from adapter if instance variable hasn't been initialized
|
|
144
149
|
loaded_value = load_value_from_adapter
|
|
145
150
|
if loaded_value.nil?
|
|
146
|
-
# Value not found in adapter, use default
|
|
151
|
+
# Value not found in adapter, use default and cache it
|
|
152
|
+
@stored_value = default_value
|
|
153
|
+
@stored_value_initialized = true
|
|
147
154
|
default_value
|
|
148
155
|
else
|
|
149
156
|
# Value found in adapter, use it and mark as initialized
|
|
@@ -827,9 +834,14 @@ module Magick
|
|
|
827
834
|
adapter_registry.set(name, 'targeting', targeting)
|
|
828
835
|
|
|
829
836
|
# Update the feature in Magick.features if it's registered
|
|
830
|
-
|
|
837
|
+
if Magick.features.key?(name)
|
|
838
|
+
Magick.features[name].instance_variable_set(:@targeting, targeting.dup)
|
|
839
|
+
# Update targeting empty cache for performance
|
|
840
|
+
Magick.features[name].instance_variable_set(:@_targeting_empty, targeting.empty?)
|
|
841
|
+
end
|
|
831
842
|
|
|
832
|
-
|
|
843
|
+
# Update local targeting empty cache for performance
|
|
844
|
+
@_targeting_empty = targeting.empty?
|
|
833
845
|
|
|
834
846
|
# Explicitly trigger cache invalidation for targeting updates
|
|
835
847
|
# Targeting changes affect enabled? checks, so we need immediate cache invalidation
|
data/lib/magick/version.rb
CHANGED