magick-feature-flags 0.9.6 → 0.9.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c89e62bee50614e51b3e844968d557e90217cd48e77bb68ec50c47d48881389b
4
- data.tar.gz: d39574add8463bb4a927ea94db047d3418317d966b77f400892f67ed6bf4a31c
3
+ metadata.gz: a7f546b5a885a633524d3b0c405e296621f00eaeabb7b65339160c5aa0911ead
4
+ data.tar.gz: 07af571d3fdba904c122c5e8996c58fcaac31d515bd955f57aa640d66373376b
5
5
  SHA512:
6
- metadata.gz: 133bbce3e15f14c39181eaf2078e0bec80fcc2aa295d85397bcb78f95400637e046dd9749f5c8ed65291f2c2e8b562ac8ced6b3df39dd3d625536a58851cefbb
7
- data.tar.gz: 3a8578be1de567da37d0393e07302934176100bed9d9239bad978c757ed65a6f58770cc3a9b6b6fb5d73fd2393007053bc43c32b466b9bd167e97d5e775c6be0
6
+ metadata.gz: 75608b0d581c01aa0a25a362bb45c6cdcb4e8b3ee0316663d1ec6e521b9af3099192d1e2a38fcc13ead9adb256c1fda09934fef749323fc7e94cbaa7daac7c3f
7
+ data.tar.gz: ca5643cbd9bdeffeb8c8e1116b4631c6bedde59c2bd050936a77b6bdece35fc67955608ecccba41a7eaaffe59da769a0b74c59f9cb57372fbd07b281c188b397
data/README.md CHANGED
@@ -82,7 +82,12 @@ Magick.configure do
82
82
  async_updates enabled: true
83
83
 
84
84
  # Enable services
85
- performance_metrics enabled: true
85
+ performance_metrics(
86
+ enabled: true,
87
+ redis_tracking: true, # Auto-enabled if Redis is configured
88
+ batch_size: 100, # Flush after 100 updates
89
+ flush_interval: 60 # Or flush every 60 seconds
90
+ )
86
91
  audit_log enabled: true
87
92
  versioning enabled: true
88
93
  warn_on_deprecated enabled: true
@@ -295,7 +300,16 @@ variant = feature.get_variant
295
300
  ```ruby
296
301
  feature = Magick[:advanced_feature]
297
302
  feature.add_dependency(:base_feature)
298
- # advanced_feature will only be enabled if base_feature is also enabled
303
+ # advanced_feature can be enabled independently
304
+ # However, base_feature (dependency) cannot be enabled if advanced_feature (main feature) is disabled
305
+ # This ensures dependencies are only enabled when their parent features are enabled
306
+
307
+ # Example:
308
+ Magick[:advanced_feature].disable # => true
309
+ Magick[:base_feature].enable # => false (cannot enable dependency when main feature is disabled)
310
+
311
+ Magick[:advanced_feature].enable # => true
312
+ Magick[:base_feature].enable # => true (now can enable dependency)
299
313
  ```
300
314
 
301
315
  #### Export/Import
@@ -322,16 +336,55 @@ Magick.versioning.rollback(:my_feature, version: 2)
322
336
  #### Performance Metrics
323
337
 
324
338
  ```ruby
325
- # Get average duration for feature checks
326
- avg_duration = Magick.performance_metrics.average_duration(feature_name: :my_feature)
339
+ # Get comprehensive stats for a feature
340
+ Magick.feature_stats(:my_feature)
341
+ # => {
342
+ # usage_count: 1250,
343
+ # average_duration: 0.032,
344
+ # average_duration_by_operation: {
345
+ # enabled: 0.032,
346
+ # value: 0.0,
347
+ # get_value: 0.0
348
+ # }
349
+ # }
350
+
351
+ # Get just the usage count
352
+ Magick.feature_usage_count(:my_feature)
353
+ # => 1250
354
+
355
+ # Get average duration (optionally filtered by operation)
356
+ Magick.feature_average_duration(:my_feature)
357
+ Magick.feature_average_duration(:my_feature, operation: 'enabled?')
327
358
 
328
359
  # Get most used features
329
- most_used = Magick.performance_metrics.most_used_features(limit: 10)
360
+ Magick.most_used_features(limit: 10)
361
+ # => {
362
+ # "my_feature" => 1250,
363
+ # "another_feature" => 890,
364
+ # ...
365
+ # }
366
+
367
+ # Direct access to performance metrics (for advanced usage)
368
+ Magick.performance_metrics.average_duration(feature_name: :my_feature)
369
+ Magick.performance_metrics.usage_count(:my_feature)
370
+ Magick.performance_metrics.most_used_features(limit: 10)
371
+ ```
372
+
373
+ **Configuration:**
330
374
 
331
- # Get usage count
332
- count = Magick.performance_metrics.usage_count(:my_feature)
375
+ ```ruby
376
+ Magick.configure do
377
+ performance_metrics(
378
+ enabled: true,
379
+ redis_tracking: true, # Auto-enabled if Redis is configured
380
+ batch_size: 100, # Flush after 100 updates
381
+ flush_interval: 60 # Or flush every 60 seconds
382
+ )
383
+ end
333
384
  ```
334
385
 
386
+ **Note:** When `redis_tracking: true` is set, usage counts are persisted to Redis and aggregated across all processes, giving you total usage statistics.
387
+
335
388
  #### Audit Logging
336
389
 
337
390
  ```ruby
@@ -351,7 +404,10 @@ Magick uses a dual-adapter strategy:
351
404
  1. **Memory Adapter**: Fast, in-memory storage with TTL support
352
405
  2. **Redis Adapter**: Persistent storage for distributed systems (optional)
353
406
 
354
- The registry automatically falls back from memory to Redis if a feature isn't found in memory. When features are updated, both adapters are updated simultaneously.
407
+ The registry automatically falls back from memory to Redis if a feature isn't found in memory. When features are updated:
408
+ - Both adapters are updated simultaneously
409
+ - Cache invalidation messages are published via Redis Pub/Sub to notify other processes
410
+ - Targeting updates trigger immediate cache invalidation to ensure consistency
355
411
 
356
412
  #### Memory-Only Mode
357
413
 
@@ -92,6 +92,11 @@ module Magick
92
92
  publish_cache_invalidation(feature_name)
93
93
  end
94
94
 
95
+ # Check if Redis adapter is available
96
+ def redis_available?
97
+ !redis_adapter.nil?
98
+ end
99
+
95
100
  private
96
101
 
97
102
  attr_reader :memory_adapter, :redis_adapter, :circuit_breaker
data/lib/magick/config.rb CHANGED
@@ -48,12 +48,16 @@ module Magick
48
48
  return unless enabled
49
49
 
50
50
  @performance_metrics = PerformanceMetrics.new(batch_size: batch_size, flush_interval: flush_interval)
51
- # Enable Redis tracking if Redis adapter is configured (or explicitly set)
52
- if redis_tracking.nil?
53
- # Auto-enable if Redis adapter exists
54
- redis_tracking = !@redis_url.nil? || configure_redis_adapter != nil
51
+ # Store redis_tracking preference for later application
52
+ @performance_metrics_redis_tracking = redis_tracking
53
+ # Enable Redis tracking if explicitly set to true, otherwise defer to apply! method
54
+ if redis_tracking == true
55
+ @performance_metrics.enable_redis_tracking(enable: true)
56
+ elsif redis_tracking == false
57
+ @performance_metrics.enable_redis_tracking(enable: false)
55
58
  end
56
- @performance_metrics.enable_redis_tracking(enable: redis_tracking) if @performance_metrics
59
+ # If nil, will be auto-determined in apply! method
60
+ @performance_metrics
57
61
  end
58
62
 
59
63
  def audit_log(enabled: true, adapter: nil)
@@ -90,15 +94,23 @@ module Magick
90
94
  def apply!
91
95
  # Apply configuration to Magick module
92
96
  Magick.adapter_registry = adapter_registry if adapter_registry
93
- Magick.performance_metrics = performance_metrics if performance_metrics
97
+
98
+ # Apply performance metrics (preserve redis_tracking setting)
99
+ if performance_metrics
100
+ Magick.performance_metrics = performance_metrics
101
+ # Re-apply redis_tracking setting after assignment (in case object was replaced)
102
+ if defined?(@performance_metrics_redis_tracking) && !@performance_metrics_redis_tracking.nil?
103
+ Magick.performance_metrics.enable_redis_tracking(enable: @performance_metrics_redis_tracking)
104
+ # Otherwise, auto-enable if Redis adapter is configured
105
+ # Check Magick.adapter_registry (after it's been set) instead of local instance variable
106
+ elsif Magick.adapter_registry.is_a?(Adapters::Registry) && Magick.adapter_registry.redis_available?
107
+ Magick.performance_metrics.enable_redis_tracking(enable: true)
108
+ end
109
+ end
110
+
94
111
  Magick.audit_log = audit_log if audit_log
95
112
  Magick.versioning = versioning if versioning
96
113
  Magick.warn_on_deprecated = warn_on_deprecated
97
-
98
- # Enable Redis tracking for performance metrics if Redis adapter is configured
99
- if Magick.performance_metrics && adapter_registry.is_a?(Adapters::Registry) && adapter_registry.redis_adapter
100
- Magick.performance_metrics.enable_redis_tracking(enable: true)
101
- end
102
114
  end
103
115
 
104
116
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Magick
4
- VERSION = '0.9.6'
4
+ VERSION = '0.9.8'
5
5
  end
data/lib/magick.rb CHANGED
@@ -128,6 +128,46 @@ module Magick
128
128
  @versioning ||= Versioning.new(adapter_registry || default_adapter_registry)
129
129
  end
130
130
 
131
+ # Manually enable Redis tracking for performance metrics
132
+ # Useful if Redis adapter becomes available after initial configuration
133
+ def enable_redis_tracking(enable: true)
134
+ return unless performance_metrics
135
+
136
+ performance_metrics.enable_redis_tracking(enable: enable)
137
+ end
138
+
139
+ # Get total usage count for a feature (combines memory and Redis counts)
140
+ def feature_stats(feature_name)
141
+ return {} unless performance_metrics
142
+
143
+ {
144
+ usage_count: performance_metrics.usage_count(feature_name),
145
+ average_duration: performance_metrics.average_duration(feature_name: feature_name),
146
+ average_duration_by_operation: {
147
+ enabled: performance_metrics.average_duration(feature_name: feature_name, operation: 'enabled?'),
148
+ value: performance_metrics.average_duration(feature_name: feature_name, operation: 'value'),
149
+ get_value: performance_metrics.average_duration(feature_name: feature_name, operation: 'get_value')
150
+ }
151
+ }
152
+ end
153
+
154
+ # Get usage count for a feature
155
+ def feature_usage_count(feature_name)
156
+ performance_metrics&.usage_count(feature_name) || 0
157
+ end
158
+
159
+ # Get average duration for a feature (optionally filtered by operation)
160
+ def feature_average_duration(feature_name, operation: nil)
161
+ return 0.0 unless performance_metrics
162
+
163
+ performance_metrics.average_duration(feature_name: feature_name, operation: operation)
164
+ end
165
+
166
+ # Get most used features
167
+ def most_used_features(limit: 10)
168
+ performance_metrics&.most_used_features(limit: limit) || {}
169
+ end
170
+
131
171
  def reset!
132
172
  @features = {}
133
173
  @adapter_registry = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magick-feature-flags
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.6
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Lobanov