optify-config 1.18.0 → 1.21.1

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: fd8f5a1196800f635ebc7f4a9c1ac020ba3cc021654fa7dbbd914d0cb6122ff0
4
- data.tar.gz: 27555219991c4a53971f29c50bf7b01ab5f40efab70c4264c4b155595d4e02e8
3
+ metadata.gz: '029bd9d7bb3680eff70b702cfca85a1b8ccf95ad96fde27b1e23a6f635b36c97'
4
+ data.tar.gz: 8cdfa212412ddb927fbfdcda7fa3c2fe658a0529af4c9ade7117bced98cce61f
5
5
  SHA512:
6
- metadata.gz: b7dda691f74e094addd304d87c184361565e9df2d604e7a13ea3bf89e7833e4ac9e3350a500cdaf7cc5f6ec4885900e7ebdebe985e73a8bb17295710eb6e49f4
7
- data.tar.gz: da0e154d813a6ee1858c25fb4ba4b62288acb639822a89567621641d0708e0682505b38fd0dfeb94e9084b195fb102d424f5aa21464a15b928f5c7d9dffdb252
6
+ metadata.gz: 9bd1a0ba1a66bc6115b9489502b1fda87d66ab22936d0b111a4204392299c7d0120660e04107caa5948c8333841246890dfb6166bb86ec8cc13b47e4ee341aa3
7
+ data.tar.gz: 03d8822a3407b6a3b317c70877244dce3000a2b9b407bce75ec0f0b2c39cf7262a37712cdac9fb8f42ab5a205050e9b49fc728ef89e810ded654da70dd78e0a8
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "optify_ruby"
3
- version = "0.20.0"
3
+ version = "0.23.0"
4
4
  edition = "2021"
5
5
 
6
6
  description = "optify bindings for Ruby"
@@ -20,7 +20,8 @@ exclude = [
20
20
  crate-type = ["cdylib"]
21
21
 
22
22
  [dependencies]
23
- magnus = "0.8.0"
24
- optify = { path = "../../../../rust/optify", version = "0.20.5" }
25
- rb-sys = { version = "*", default-features = false, features = ["ruby-static"] }
23
+ magnus = "0.8.2"
24
+ # Can't put a relative path here because then others can't install the source gem: https://github.com/juharris/optify/pull/176
25
+ optify = "1.0.0"
26
+ rb-sys = { version = "0.9.124", default-features = false, features = ["ruby-static"] }
26
27
  serde_json = "1.0.143"
@@ -1,4 +1,7 @@
1
- use magnus::{function, method, prelude::*, wrap, Object, Ruby, Value as RbValue};
1
+ use magnus::{
2
+ exception::ExceptionClass, function, method, prelude::*, wrap, Object, RModule, Ruby,
3
+ Value as RbValue,
4
+ };
2
5
  use optify::builder::OptionsProviderBuilder;
3
6
  use optify::builder::OptionsRegistryBuilder;
4
7
  use optify::builder::OptionsWatcherBuilder;
@@ -13,6 +16,24 @@ use crate::preferences::MutGetOptionsPreferences;
13
16
 
14
17
  mod preferences;
15
18
 
19
+ const UNKNOWN_FEATURE_PATTERN: &str = "is not a known feature.";
20
+
21
+ fn get_unknown_feature_error(ruby: &Ruby) -> Result<ExceptionClass, magnus::Error> {
22
+ let module: RModule = ruby.class_object().const_get("Optify")?;
23
+ module.const_get("UnknownFeatureError")
24
+ }
25
+
26
+ fn map_feature_error(ruby: &Ruby, error: String) -> magnus::Error {
27
+ if error.contains(UNKNOWN_FEATURE_PATTERN) {
28
+ match get_unknown_feature_error(ruby) {
29
+ Ok(exception_class) => magnus::Error::new(exception_class, error),
30
+ Err(_) => magnus::Error::new(ruby.exception_runtime_error(), error),
31
+ }
32
+ } else {
33
+ magnus::Error::new(ruby.exception_runtime_error(), error)
34
+ }
35
+ }
36
+
16
37
  fn json_value_to_ruby(ruby: &Ruby, value: &serde_json::Value) -> Result<RbValue, magnus::Error> {
17
38
  match value {
18
39
  serde_json::Value::Null => Ok(ruby.qnil().as_value()),
@@ -117,7 +138,7 @@ impl WrappedOptionsProvider {
117
138
  .get_all_options(&feature_names, None, Some(preferences))
118
139
  {
119
140
  Ok(options) => Ok(options.to_string()),
120
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
141
+ Err(e) => Err(map_feature_error(ruby, e)),
121
142
  }
122
143
  }
123
144
 
@@ -134,7 +155,7 @@ impl WrappedOptionsProvider {
134
155
  .get_all_options(&feature_names, None, Some(preferences))
135
156
  {
136
157
  Ok(options) => json_value_to_ruby(ruby, &options),
137
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
158
+ Err(e) => Err(map_feature_error(ruby, e)),
138
159
  }
139
160
  }
140
161
 
@@ -147,7 +168,7 @@ impl WrappedOptionsProvider {
147
168
  .0
148
169
  .borrow()
149
170
  .get_canonical_feature_name(&feature_name)
150
- .map_err(|e| magnus::Error::new(ruby.exception_arg_error(), e))
171
+ .map_err(|e| map_feature_error(ruby, e))
151
172
  }
152
173
 
153
174
  fn get_canonical_feature_names(
@@ -159,7 +180,7 @@ impl WrappedOptionsProvider {
159
180
  .0
160
181
  .borrow()
161
182
  .get_canonical_feature_names(&feature_names)
162
- .map_err(|e| magnus::Error::new(ruby.exception_arg_error(), e))
183
+ .map_err(|e| map_feature_error(ruby, e))
163
184
  }
164
185
 
165
186
  fn get_feature_metadata_json(&self, canonical_feature_name: String) -> Option<String> {
@@ -191,7 +212,7 @@ impl WrappedOptionsProvider {
191
212
  .get_filtered_feature_names(&feature_names, Some(preferences))
192
213
  {
193
214
  Ok(features) => Ok(features),
194
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
215
+ Err(e) => Err(map_feature_error(ruby, e)),
195
216
  }
196
217
  }
197
218
 
@@ -208,7 +229,7 @@ impl WrappedOptionsProvider {
208
229
  .get_options_with_preferences(&key, &feature_names, None, None)
209
230
  {
210
231
  Ok(options) => Ok(options.to_string()),
211
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
232
+ Err(e) => Err(map_feature_error(ruby, e)),
212
233
  }
213
234
  }
214
235
 
@@ -227,7 +248,7 @@ impl WrappedOptionsProvider {
227
248
  Some(preferences),
228
249
  ) {
229
250
  Ok(options) => Ok(options.to_string()),
230
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
251
+ Err(e) => Err(map_feature_error(ruby, e)),
231
252
  }
232
253
  }
233
254
 
@@ -243,7 +264,7 @@ impl WrappedOptionsProvider {
243
264
  .get_options_with_preferences(&key, &feature_names, None, None)
244
265
  {
245
266
  Ok(options) => json_value_to_ruby(ruby, &options),
246
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
267
+ Err(e) => Err(map_feature_error(ruby, e)),
247
268
  }
248
269
  }
249
270
 
@@ -262,13 +283,30 @@ impl WrappedOptionsProvider {
262
283
  Some(preferences),
263
284
  ) {
264
285
  Ok(options) => json_value_to_ruby(ruby, &options),
265
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
286
+ Err(e) => Err(map_feature_error(ruby, e)),
266
287
  }
267
288
  }
268
289
 
269
290
  fn has_conditions(&self, canonical_feature_name: String) -> bool {
270
291
  self.0.borrow().has_conditions(&canonical_feature_name)
271
292
  }
293
+
294
+ fn map_feature_names(
295
+ ruby: &Ruby,
296
+ rb_self: &Self,
297
+ feature_names: Vec<String>,
298
+ preferences: &MutGetOptionsPreferences,
299
+ ) -> Result<Vec<Option<String>>, magnus::Error> {
300
+ let preferences = &convert_preferences(preferences);
301
+ match rb_self
302
+ .0
303
+ .borrow()
304
+ .map_feature_names(&feature_names, Some(preferences))
305
+ {
306
+ Ok(features) => Ok(features),
307
+ Err(e) => Err(map_feature_error(ruby, e)),
308
+ }
309
+ }
272
310
  }
273
311
 
274
312
  #[derive(Clone)]
@@ -363,7 +401,7 @@ impl WrappedOptionsWatcher {
363
401
  .get_all_options(&feature_names, None, Some(preferences))
364
402
  {
365
403
  Ok(options) => Ok(options.to_string()),
366
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
404
+ Err(e) => Err(map_feature_error(ruby, e)),
367
405
  }
368
406
  }
369
407
 
@@ -380,7 +418,7 @@ impl WrappedOptionsWatcher {
380
418
  .get_all_options(&feature_names, None, Some(preferences))
381
419
  {
382
420
  Ok(options) => json_value_to_ruby(ruby, &options),
383
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
421
+ Err(e) => Err(map_feature_error(ruby, e)),
384
422
  }
385
423
  }
386
424
 
@@ -393,7 +431,7 @@ impl WrappedOptionsWatcher {
393
431
  .0
394
432
  .borrow()
395
433
  .get_canonical_feature_name(&feature_name)
396
- .map_err(|e| magnus::Error::new(ruby.exception_arg_error(), e))
434
+ .map_err(|e| map_feature_error(ruby, e))
397
435
  }
398
436
 
399
437
  fn get_canonical_feature_names(
@@ -405,7 +443,7 @@ impl WrappedOptionsWatcher {
405
443
  .0
406
444
  .borrow()
407
445
  .get_canonical_feature_names(&feature_names)
408
- .map_err(|e| magnus::Error::new(ruby.exception_arg_error(), e))
446
+ .map_err(|e| map_feature_error(ruby, e))
409
447
  }
410
448
 
411
449
  fn get_feature_metadata_json(&self, canonical_feature_name: String) -> Option<String> {
@@ -436,7 +474,7 @@ impl WrappedOptionsWatcher {
436
474
  .get_filtered_feature_names(&feature_names, Some(preferences))
437
475
  {
438
476
  Ok(features) => Ok(features),
439
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
477
+ Err(e) => Err(map_feature_error(ruby, e)),
440
478
  }
441
479
  }
442
480
 
@@ -452,7 +490,7 @@ impl WrappedOptionsWatcher {
452
490
  .get_options_with_preferences(&key, &feature_names, None, None)
453
491
  {
454
492
  Ok(options) => Ok(options.to_string()),
455
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
493
+ Err(e) => Err(map_feature_error(ruby, e)),
456
494
  }
457
495
  }
458
496
 
@@ -471,7 +509,7 @@ impl WrappedOptionsWatcher {
471
509
  Some(preferences),
472
510
  ) {
473
511
  Ok(options) => Ok(options.to_string()),
474
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
512
+ Err(e) => Err(map_feature_error(ruby, e)),
475
513
  }
476
514
  }
477
515
 
@@ -487,7 +525,7 @@ impl WrappedOptionsWatcher {
487
525
  .get_options_with_preferences(&key, &feature_names, None, None)
488
526
  {
489
527
  Ok(options) => json_value_to_ruby(ruby, &options),
490
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
528
+ Err(e) => Err(map_feature_error(ruby, e)),
491
529
  }
492
530
  }
493
531
 
@@ -506,7 +544,7 @@ impl WrappedOptionsWatcher {
506
544
  Some(preferences),
507
545
  ) {
508
546
  Ok(options) => json_value_to_ruby(ruby, &options),
509
- Err(e) => Err(magnus::Error::new(ruby.exception_runtime_error(), e)),
547
+ Err(e) => Err(map_feature_error(ruby, e)),
510
548
  }
511
549
  }
512
550
 
@@ -517,6 +555,23 @@ impl WrappedOptionsWatcher {
517
555
  fn last_modified(&self) -> std::time::SystemTime {
518
556
  self.0.borrow().last_modified()
519
557
  }
558
+
559
+ fn map_feature_names(
560
+ ruby: &Ruby,
561
+ rb_self: &Self,
562
+ feature_names: Vec<String>,
563
+ preferences: &MutGetOptionsPreferences,
564
+ ) -> Result<Vec<Option<String>>, magnus::Error> {
565
+ let preferences = &convert_preferences(preferences);
566
+ match rb_self
567
+ .0
568
+ .borrow()
569
+ .map_feature_names(&feature_names, Some(preferences))
570
+ {
571
+ Ok(features) => Ok(features),
572
+ Err(e) => Err(map_feature_error(ruby, e)),
573
+ }
574
+ }
520
575
  }
521
576
 
522
577
  #[derive(Clone)]
@@ -551,6 +606,8 @@ impl WrappedOptionsWatcherBuilder {
551
606
  fn init(ruby: &Ruby) -> Result<(), magnus::Error> {
552
607
  let module = ruby.define_module("Optify")?;
553
608
 
609
+ module.define_error("UnknownFeatureError", ruby.exception_standard_error())?;
610
+
554
611
  let builder_class = module.define_class("OptionsProviderBuilder", ruby.class_object())?;
555
612
 
556
613
  builder_class
@@ -620,6 +677,10 @@ fn init(ruby: &Ruby) -> Result<(), magnus::Error> {
620
677
  "conditions?",
621
678
  method!(WrappedOptionsProvider::has_conditions, 1),
622
679
  )?;
680
+ provider_class.define_method(
681
+ "map_feature_names",
682
+ method!(WrappedOptionsProvider::map_feature_names, 2),
683
+ )?;
623
684
 
624
685
  // Private methods for internal use.
625
686
  provider_class.define_private_method(
@@ -759,6 +820,10 @@ fn init(ruby: &Ruby) -> Result<(), magnus::Error> {
759
820
  "last_modified",
760
821
  method!(WrappedOptionsWatcher::last_modified, 0),
761
822
  )?;
823
+ watcher_class.define_method(
824
+ "map_feature_names",
825
+ method!(WrappedOptionsWatcher::map_feature_names, 2),
826
+ )?;
762
827
 
763
828
  // Private methods for internal use.
764
829
  watcher_class.define_private_method(
@@ -0,0 +1,41 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Optify
5
+ # The mode for the cache.
6
+ module CacheMode
7
+ # Non-thread-safe LRU cache.
8
+ # Should be faster than `THREAD_SAFE` for single-threaded applications.
9
+ NOT_THREAD_SAFE = :not_thread_safe #: Symbol
10
+ # Thread-safe LRU cache.
11
+ THREAD_SAFE = :thread_safe #: Symbol
12
+ end
13
+
14
+ # Options for initializing the cache.
15
+ class CacheInitOptions
16
+ #: Integer?
17
+ attr_reader :max_size
18
+
19
+ # A value from `CacheMode`.
20
+ #
21
+ #: Symbol
22
+ attr_reader :mode
23
+
24
+ # Initializes the cache options.
25
+ # Defaults to a non-thread-safe unlimited size cache for backwards compatibility
26
+ # with how this library was originally configured with an unbounded hash as the base.
27
+ # @param mode A value from `CacheMode`.
28
+ #
29
+ #: (
30
+ #| ?max_size: Integer?,
31
+ #| ?mode: Symbol,
32
+ #| ) -> void
33
+ def initialize(
34
+ max_size: nil,
35
+ mode: CacheMode::NOT_THREAD_SAFE
36
+ )
37
+ @max_size = max_size
38
+ @mode = mode
39
+ end
40
+ end
41
+ end
@@ -4,6 +4,7 @@
4
4
  require 'sorbet-runtime'
5
5
 
6
6
  require_relative './base_config'
7
+ require_relative './cache_init_options'
7
8
  require_relative './options_metadata'
8
9
  require_relative './provider_module'
9
10
 
@@ -32,9 +33,9 @@ module Optify
32
33
 
33
34
  # (Optional) Eagerly initializes the cache.
34
35
  # @return [OptionsProvider] `self`.
35
- #: -> OptionsProvider
36
- def init
37
- _init
36
+ #: (?CacheInitOptions?) -> OptionsProvider
37
+ def init(cache_init_options = nil)
38
+ _init(cache_init_options)
38
39
  self
39
40
  end
40
41
  end
@@ -2,11 +2,47 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'json'
5
+ require 'lru_redux'
5
6
  require 'sorbet-runtime'
6
7
 
7
8
  module Optify
8
9
  # @!visibility private
9
10
  module ProviderModule
11
+ #: [T] (LruRedux::Cache | Hash[untyped, untyped], Array[untyped]) { -> T } -> T
12
+ def self._cache_getset(cache, cache_key, &block)
13
+ if cache.is_a? LruRedux::Cache
14
+ cache.getset(cache_key, &block)
15
+ else
16
+ # Plain Hash - use fetch with block and store result
17
+ cache.fetch(cache_key) do
18
+ result = block.call
19
+ cache[cache_key] = result
20
+ end
21
+ end
22
+ end
23
+
24
+ #: (CacheInitOptions?) -> ( Hash[Array[untyped], untyped] | LruRedux::Cache)
25
+ def self._create_cache(cache_init_options)
26
+ # Be backwards compatible with the original implementation of this library.
27
+ return {} if cache_init_options.nil?
28
+
29
+ max_size = cache_init_options.max_size
30
+ mode = cache_init_options.mode
31
+ if max_size.nil?
32
+ Kernel.raise ArgumentError, 'Thread-safe cache is not supported when max_size is nil' if mode == CacheMode::THREAD_SAFE
33
+ {}
34
+ else
35
+ case mode
36
+ when CacheMode::THREAD_SAFE
37
+ LruRedux::ThreadSafeCache.new(max_size)
38
+ when CacheMode::NOT_THREAD_SAFE
39
+ LruRedux::Cache.new(max_size)
40
+ else
41
+ Kernel.raise ArgumentError, "Invalid cache mode: #{mode}"
42
+ end
43
+ end
44
+ end
45
+
10
46
  #: (Array[String] feature_names) -> Array[String]
11
47
  def get_canonical_feature_names(feature_names)
12
48
  # Try to optimize a typical case where there are just a few features.
@@ -55,7 +91,7 @@ module Optify
55
91
  # @return The options.
56
92
  #: [Config] (String, Array[String], Class[Config], ?CacheOptions?, ?Optify::GetOptionsPreferences?) -> Config
57
93
  def _get_options(key, feature_names, config_class, cache_options = nil, preferences = nil)
58
- return get_options_with_cache(key, feature_names, config_class, cache_options, preferences) if cache_options
94
+ return _get_options_with_cache(key, feature_names, config_class, cache_options, preferences) if cache_options
59
95
 
60
96
  unless config_class.respond_to?(:from_hash)
61
97
  Kernel.raise NotImplementedError,
@@ -73,14 +109,8 @@ module Optify
73
109
  .from_hash(hash)
74
110
  end
75
111
 
76
- #: -> void
77
- def _init
78
- @cache = {} #: Hash[untyped, untyped]?
79
- @features_with_metadata = nil #: Hash[String, OptionsMetadata]?
80
- end
81
-
82
112
  #: [Config] (String key, Array[String] feature_names, Class[Config] config_class, Optify::CacheOptions _cache_options, ?Optify::GetOptionsPreferences? preferences) -> Config
83
- def get_options_with_cache(key, feature_names, config_class, _cache_options, preferences = nil)
113
+ def _get_options_with_cache(key, feature_names, config_class, _cache_options, preferences = nil)
84
114
  # Cache directly in Ruby instead of Rust because:
85
115
  # * Avoid any possible conversion overhead.
86
116
  # * Memory management: probably better to do it in Ruby for a Ruby app and avoid memory in Rust.
@@ -100,22 +130,27 @@ module Optify
100
130
  # Features are filtered, so we don't need the constraints in the cache key.
101
131
  are_configurable_strings_enabled = preferences&.are_configurable_strings_enabled? || false
102
132
  cache_key = [key, feature_names, are_configurable_strings_enabled, config_class]
103
- @cache #: as !nil
104
- .fetch(cache_key) do
133
+ ProviderModule._cache_getset(
134
+ @cache, #: as !nil
135
+ cache_key,
136
+ ) do
105
137
  # Handle a cache miss.
106
138
 
107
139
  # We can avoid converting the features names because they're already converted from filtering above, if that was desired.
108
140
  # We don't need the constraints because we filtered the features above.
109
141
  # We already know there are no overrides because we checked above.
110
- preferences = GetOptionsPreferences.new
111
- preferences.skip_feature_name_conversion = true
112
- preferences.enable_configurable_strings if are_configurable_strings_enabled
142
+ cache_miss_preferences = GetOptionsPreferences.new
143
+ cache_miss_preferences.skip_feature_name_conversion = true
144
+ cache_miss_preferences.enable_configurable_strings if are_configurable_strings_enabled
113
145
 
114
- result = _get_options(key, feature_names, config_class, nil, preferences)
115
-
116
- @cache #: as !nil
117
- .[]= cache_key, result
146
+ _get_options(key, feature_names, config_class, nil, cache_miss_preferences)
118
147
  end
119
148
  end
149
+
150
+ #: (?CacheInitOptions?) -> void
151
+ def _init(cache_init_options = nil)
152
+ @cache = ProviderModule._create_cache(cache_init_options) #: ( Hash[untyped, untyped] | LruRedux::Cache)?
153
+ @features_with_metadata = nil #: Hash[String, OptionsMetadata]?
154
+ end
120
155
  end
121
156
  end
@@ -30,9 +30,9 @@ module Optify
30
30
 
31
31
  # (Optional) Eagerly initializes the cache.
32
32
  # @return [OptionsWatcher] `self`.
33
- #: -> OptionsWatcher
34
- def init
35
- _init
33
+ #: (?CacheInitOptions?) -> OptionsWatcher
34
+ def init(cache_init_options = nil)
35
+ _init(cache_init_options)
36
36
  @cache_creation_time = Time.now #: Time?
37
37
  self
38
38
  end
data/rbi/optify.rbi CHANGED
@@ -3,6 +3,10 @@
3
3
 
4
4
  # Tools for working with configurations declared in files.
5
5
  module Optify
6
+ # Raised when a feature name is not found in the registry.
7
+ class UnknownFeatureError < StandardError
8
+ end
9
+
6
10
  # DEPRECATED: Use `Optify::FromHashable` instead.
7
11
  # A base class for classes from configuration files.
8
12
  # Classes that derive from this can easily be used with `Optify::OptionsProvider.get_options`
@@ -19,6 +23,37 @@ module Optify
19
23
  class CacheOptions < FromHashable
20
24
  end
21
25
 
26
+ # The mode for the cache.
27
+ module CacheMode
28
+ # Non-thread-safe LRU cache.
29
+ # Should be faster than `THREAD_SAFE` for single-threaded applications.
30
+ NOT_THREAD_SAFE = T.let(:not_thread_safe, Symbol)
31
+ # Thread-safe LRU cache.
32
+ THREAD_SAFE = T.let(:thread_safe, Symbol)
33
+ end
34
+
35
+ # Options for initializing the cache.
36
+ class CacheInitOptions
37
+ sig { returns(T.nilable(Integer)) }
38
+ attr_reader :max_size
39
+
40
+ # A value from `CacheMode`.
41
+ sig { returns(Symbol) }
42
+ attr_reader :mode
43
+
44
+ # Initializes the cache options.
45
+ # Defaults to a non-thread-safe unlimited size cache for backwards compatibility
46
+ # with how this library was originally configured with an unbounded hash as the base.
47
+ # @param mode A value from `CacheMode`.
48
+ sig do
49
+ params(
50
+ max_size: T.nilable(Integer),
51
+ mode: Symbol,
52
+ ).void
53
+ end
54
+ def initialize(max_size: nil, mode: CacheMode::NOT_THREAD_SAFE); end
55
+ end
56
+
22
57
  # Information about a feature.
23
58
  class OptionsMetadata < FromHashable
24
59
  sig { returns(T.nilable(T::Array[String])) }
@@ -161,6 +196,15 @@ module Optify
161
196
  # Some of the methods shown within this module are implemented in Rust
162
197
  # and are declared in this common module to avoid duplicate declarations in different classes.
163
198
  module ProviderModule
199
+ # @param canonical_feature_name [String] A canonical feature name
200
+ # @return Whether the feature has conditions.
201
+ sig { params(canonical_feature_name: String).returns(T::Boolean) }
202
+ def conditions?(canonical_feature_name); end
203
+
204
+ # @return All of the keys and values for the the features.
205
+ sig { returns(String) }
206
+ def features_with_metadata_json; end
207
+
164
208
  # Map an alias or canonical feature name (perhaps derived from a file name) to a canonical feature name.
165
209
  # Canonical feature names map to themselves.
166
210
  #
@@ -188,7 +232,7 @@ module Optify
188
232
  sig do
189
233
  params(
190
234
  feature_names: T::Array[String],
191
- preferences: GetOptionsPreferences
235
+ preferences: GetOptionsPreferences,
192
236
  )
193
237
  .returns(T::Array[String])
194
238
  end
@@ -211,7 +255,7 @@ module Optify
211
255
  feature_names: T::Array[String],
212
256
  config_class: T::Class[T.type_parameter(:Config)],
213
257
  cache_options: T.nilable(CacheOptions),
214
- preferences: T.nilable(Optify::GetOptionsPreferences)
258
+ preferences: T.nilable(Optify::GetOptionsPreferences),
215
259
  )
216
260
  .returns(T.type_parameter(:Config))
217
261
  end
@@ -257,15 +301,25 @@ module Optify
257
301
  end
258
302
  def get_options_json_with_preferences(key, feature_names, preferences); end
259
303
 
260
- # @param canonical_feature_name [String] A canonical feature name
261
- # @return Whether the feature has conditions.
262
- sig { params(canonical_feature_name: String).returns(T::Boolean) }
263
- def conditions?(canonical_feature_name); end
264
-
265
304
  # (Optional) Eagerly initializes the cache.
266
305
  # @return `self`.
267
- sig { returns(T.self_type) }
268
- def init; end
306
+ sig do
307
+ params(cache_init_options: T.nilable(CacheInitOptions))
308
+ .returns(T.self_type)
309
+ end
310
+ def init(cache_init_options = nil); end
311
+
312
+ # Filters `feature_names` based on the preferences,
313
+ # such as the `preferences`'s constraints.
314
+ # Returns an array matching the input order where each element is the canonical name if the feature was kept, or nil if it was filtered out.
315
+ sig do
316
+ params(
317
+ feature_names: T::Array[String],
318
+ preferences: GetOptionsPreferences,
319
+ )
320
+ .returns(T::Array[T.nilable(String)])
321
+ end
322
+ def map_feature_names(feature_names, preferences); end
269
323
 
270
324
  private
271
325
 
@@ -281,10 +335,6 @@ module Optify
281
335
  # @return The metadata for the feature.
282
336
  sig { params(canonical_feature_name: String).returns(T.nilable(String)) }
283
337
  def get_feature_metadata_json(canonical_feature_name); end
284
-
285
- # @return All of the keys and values for the the features.
286
- sig { returns(String) }
287
- def features_with_metadata_json; end
288
338
  end
289
339
 
290
340
  # Provides configurations based on keys and enabled feature names.
data/sig/optify.rbs CHANGED
@@ -2,6 +2,10 @@
2
2
  module Optify
3
3
  end
4
4
 
5
+ # Raised when a feature name is not found in the registry.
6
+ class Optify::UnknownFeatureError < StandardError
7
+ end
8
+
5
9
  # DEPRECATED: Use `Optify::FromHashable` instead.
6
10
  # A base class for classes from configuration files.
7
11
  # Classes that derive from this can easily be used with `Optify::OptionsProvider.get_options`
@@ -17,6 +21,22 @@ end
17
21
  class Optify::CacheOptions < FromHashable
18
22
  end
19
23
 
24
+ # The mode for the cache.
25
+ module Optify::CacheMode
26
+ end
27
+
28
+ Optify::Optify::CacheMode::NOT_THREAD_SAFE: Symbol
29
+
30
+ Optify::Optify::CacheMode::THREAD_SAFE: Symbol
31
+
32
+ # Options for initializing the cache.
33
+ class Optify::CacheInitOptions
34
+ # A value from `CacheMode`.
35
+ def initialize: () -> Integer?
36
+ | () -> Symbol
37
+ | (?max_size: Integer? max_size, ?mode: Symbol mode) -> void
38
+ end
39
+
20
40
  # Information about a feature.
21
41
  class Optify::OptionsMetadata < FromHashable
22
42
  def aliases: () -> ::Array[String]?
@@ -119,6 +139,13 @@ end
119
139
  # Some of the methods shown within this module are implemented in Rust
120
140
  # and are declared in this common module to avoid duplicate declarations in different classes.
121
141
  module Optify::ProviderModule
142
+ # @param canonical_feature_name [String] A canonical feature name
143
+ # @return Whether the feature has conditions.
144
+ def conditions?: (String canonical_feature_name) -> bool
145
+
146
+ # @return All of the keys and values for the the features.
147
+ def features_with_metadata_json: () -> String
148
+
122
149
  # Map an alias or canonical feature name (perhaps derived from a file name) to a canonical feature name.
123
150
  # Canonical feature names map to themselves.
124
151
  #
@@ -159,13 +186,9 @@ module Optify::ProviderModule
159
186
 
160
187
  def get_options_json_with_preferences: (String key, ::Array[String] feature_names, GetOptionsPreferences preferences) -> String
161
188
 
162
- # @param canonical_feature_name [String] A canonical feature name
163
- # @return Whether the feature has conditions.
164
- def conditions?: (String canonical_feature_name) -> bool
189
+ def init: (?CacheInitOptions? cache_init_options) -> self
165
190
 
166
- # (Optional) Eagerly initializes the cache.
167
- # @return `self`.
168
- def init: () -> self
191
+ def map_feature_names: (::Array[String] feature_names, GetOptionsPreferences preferences) -> ::Array[String?]
169
192
 
170
193
  # Map aliases or canonical feature names (perhaps derived from a file names) to the canonical feature names.
171
194
  # Canonical feature names map to themselves.
@@ -177,9 +200,6 @@ module Optify::ProviderModule
177
200
 
178
201
  # @return The metadata for the feature.
179
202
  def get_feature_metadata_json: (String canonical_feature_name) -> String?
180
-
181
- # @return All of the keys and values for the the features.
182
- def features_with_metadata_json: () -> String
183
203
  end
184
204
 
185
205
  # Provides configurations based on keys and enabled feature names.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optify-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.18.0
4
+ version: 1.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin D. Harris
@@ -15,28 +15,42 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.9.117
18
+ version: 0.9.124
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.9.117
25
+ version: 0.9.124
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: optify-from_hash
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.2.1
32
+ version: 0.2.2
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.2.1
39
+ version: 0.2.2
40
+ - !ruby/object:Gem::Dependency
41
+ name: sin_lru_redux
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.5.2
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 2.5.2
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: sorbet-runtime
42
56
  requirement: !ruby/object:Gem::Requirement
@@ -91,14 +105,14 @@ dependencies:
91
105
  requirements:
92
106
  - - "~>"
93
107
  - !ruby/object:Gem::Version
94
- version: 1.76.1
108
+ version: 1.82.1
95
109
  type: :development
96
110
  prerelease: false
97
111
  version_requirements: !ruby/object:Gem::Requirement
98
112
  requirements:
99
113
  - - "~>"
100
114
  - !ruby/object:Gem::Version
101
- version: 1.76.1
115
+ version: 1.82.1
102
116
  - !ruby/object:Gem::Dependency
103
117
  name: rubocop-sorbet
104
118
  requirement: !ruby/object:Gem::Requirement
@@ -175,6 +189,7 @@ files:
175
189
  - ext/optify_ruby/src/preferences.rs
176
190
  - lib/optify.rb
177
191
  - lib/optify_ruby/base_config.rb
192
+ - lib/optify_ruby/cache_init_options.rb
178
193
  - lib/optify_ruby/get_options_preferences.rb
179
194
  - lib/optify_ruby/implementation.rb
180
195
  - lib/optify_ruby/options_metadata.rb