You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit e89cf98
Browse filesBrowse the repository at this point in the historyBrowse files
-[Sticky features and variables](#sticky-features-and-variables)
24
25
-[Initialize with sticky](#initialize-with-sticky)
25
26
-[Set sticky afterwards](#set-sticky-afterwards)
26
27
-[Setting datafile](#setting-datafile)
@@ -36,7 +37,7 @@ This SDK is compatible with Featurevisor v3 projects and v2 datafiles.
36
37
-[Events](#events)
37
38
-[`datafile_set`](#datafile_set)
38
39
-[`context_set`](#context_set)
39
-
-[`sticky_set`](#sticky_set)
40
+
-[`sticky_features_set` and `sticky_variables_set`](#sticky_features_set-and-sticky_variables_set)
40
41
-[`error`](#error)
41
42
-[Modules](#modules)
42
43
-[Defining a module](#defining-a-module)
@@ -89,7 +90,7 @@ f = Featurevisor.create_featurevisor(
89
90
90
91
Most applications only need this factory and the returned `Featurevisor::Instance`. Public extension and observability APIs include modules, diagnostics, events, and the datafile structures accepted by the factory.
91
92
92
-
Concurrent evaluations are safe after an instance is configured. Do not mutate or close the same instance concurrently with evaluations. Serialize calls to `set_datafile`, `set_context`, `set_sticky`, `add_module`, `remove_module`, and `close`. Module, event, and diagnostic callbacks must synchronize mutable state that they capture.
93
+
Concurrent evaluations are safe after an instance is configured. Do not mutate or close the same instance concurrently with evaluations. Serialize calls to `set_datafile`, `set_context`, `set_sticky_features`, `set_sticky_variables`, `add_module`, `remove_module`, and `close`. Module, event, and diagnostic callbacks must synchronize mutable state that they capture.
Type specific methods do not coerce values. `get_variable_integer` returns `nil` for the string `"1"`, and boolean getters return `nil` for non-boolean values.
297
298
298
-
## Getting all evaluations
299
+
## Getting global variables
300
+
301
+
Global variables use the same methods with a single variable key:
Global variables resolve sticky values first, then required features, then the first matching override, and finally their default value.
310
+
311
+
## Getting aggregate evaluations
299
312
300
313
You can get evaluations of all features available in the SDK instance:
301
314
302
315
```ruby
303
-
all_evaluations = f.get_all_evaluations({})
316
+
all_evaluations = f.get_feature_evaluations({})
304
317
305
318
puts all_evaluations
306
319
# {
@@ -321,19 +334,25 @@ puts all_evaluations
321
334
322
335
This is handy especially when you want to pass all evaluations from a backend application to the frontend.
323
336
324
-
## Sticky
337
+
Global variable values are available separately:
338
+
339
+
```ruby
340
+
global_variables= f.get_variable_evaluations({})
341
+
```
342
+
343
+
## Sticky features and variables
325
344
326
345
For the lifecycle of the SDK instance in your application, you can set some features with sticky values, meaning that they will not be evaluated against the fetched [datafile](https://featurevisor.com/docs/building-datafiles/):
327
346
328
-
Sticky values belong to an SDK or child instance. Evaluation options do not accept sticky overrides; use `spawn(context, sticky: ...)` when a child needs its own sticky state.
347
+
Sticky values belong to an SDK or child instance. Feature and global variable sticky values are independent.
329
348
330
349
### Initialize with sticky
331
350
332
351
```ruby
333
352
require'featurevisor'
334
353
335
354
f =Featurevisor.create_featurevisor(
336
-
sticky: {
355
+
sticky_features: {
337
356
myFeatureKey: {
338
357
enabled:true,
339
358
# optional
@@ -345,6 +364,9 @@ f = Featurevisor.create_featurevisor(
345
364
anotherFeatureKey: {
346
365
enabled:false
347
366
}
367
+
},
368
+
sticky_variables: {
369
+
welcomeMessage:'Welcome back'
348
370
}
349
371
)
350
372
```
@@ -356,7 +378,7 @@ Once initialized with sticky features, the SDK will look for values there first
356
378
You can also set sticky features after the SDK is initialized:
357
379
358
380
```ruby
359
-
f.set_sticky({
381
+
f.set_sticky_features({
360
382
myFeatureKey: {
361
383
enabled:true,
362
384
variation:'treatment',
@@ -368,6 +390,8 @@ f.set_sticky({
368
390
enabled:false
369
391
}
370
392
}, true) # replace existing sticky features (false by default)
@@ -393,7 +417,7 @@ By default, `set_datafile(datafile)` merges the incoming datafile into the SDK's
393
417
-`segments` are merged, with incoming entries overriding existing ones
394
418
-`features` are merged, with incoming entries overriding existing ones
395
419
396
-
This means you can call `set_datafile` more than once with different datafiles, and the SDK instance accumulates their featuresand segments together.
420
+
This means you can call `set_datafile` more than once with different datafiles, and the SDK instance accumulates their features, segments, and global variables together.
397
421
398
422
### Replacing
399
423
@@ -545,15 +569,19 @@ unsubscribe = f.on('context_set') do |event|
545
569
end
546
570
```
547
571
548
-
### `sticky_set`
572
+
### `sticky_features_set` and `sticky_variables_set`
549
573
550
574
```ruby
551
-
unsubscribe= f.on('sticky_set') do |event|
575
+
feature_unsubscribe= f.on('sticky_features_set') do |event|
552
576
replaced = event[:replaced] # true if sticky features got replaced
553
577
features = event[:features] # list of all affected feature keys
554
578
555
579
puts'Sticky features set'
556
580
end
581
+
582
+
variable_unsubscribe = f.on('sticky_variables_set') do |event|
The returned object will always contain the following properties:
589
620
590
-
-`feature_key`: the feature key
621
+
-`feature_key`: the feature key when evaluating a feature
591
622
-`reason`: the reason how the value was evaluated
592
623
593
624
And optionally these properties depending on whether you are evaluating a feature variation or a variable:
@@ -606,6 +637,8 @@ And optionally these properties depending on whether you are evaluating a featur
606
637
607
638
Modules allow you to intercept the evaluation process and customize SDK behavior.
608
639
640
+
For feature evaluations, all `before` callbacks run in registration order, followed by all `before_evaluation` callbacks. After evaluation and caller defaults, all `after_evaluation` callbacks run, followed by all `after` callbacks. Global variable evaluations use only `before_evaluation` and `after_evaluation`. Required feature checks run through the complete module pipeline, and transformed defaults are preserved.
641
+
609
642
### Defining a module
610
643
611
644
A module is a simple hash with a unique recommended `name` and optional lifecycle functions:
@@ -639,6 +672,9 @@ my_custom_module = {
639
672
options
640
673
},
641
674
675
+
# unified callback for feature and global variable evaluations
676
+
before_evaluation:->(options) { options },
677
+
642
678
# after evaluation
643
679
after:->(evaluation, options) {
644
680
reason = evaluation[:reason]
@@ -648,6 +684,9 @@ my_custom_module = {
648
684
end
649
685
},
650
686
687
+
# unified callback for feature and global variable evaluations
Similar to parent SDK, child instances also support several additional methods:
726
766
727
767
-`set_context`
728
-
-`set_sticky`
768
+
-`set_sticky_features`
769
+
-`set_sticky_variables`
729
770
-`evaluate_flag`
730
771
-`is_enabled`
731
772
-`evaluate_variation`
@@ -739,7 +780,8 @@ Similar to parent SDK, child instances also support several additional methods:
739
780
-`get_variable_array`
740
781
-`get_variable_object`
741
782
-`get_variable_json`
742
-
-`get_all_evaluations`
783
+
-`get_feature_evaluations`
784
+
-`get_variable_evaluations`
743
785
-`on`
744
786
-`close`
745
787
@@ -828,7 +870,7 @@ The provider currently requires Ruby 3.4 or newer because that is the minimum ve
828
870
Install the provider:
829
871
830
872
```ruby
831
-
gem "featurevisor-openfeature", "~> 2.0"
873
+
gem "featurevisor-openfeature", "~> 3.0"
832
874
```
833
875
834
876
It installs the matching `featurevisor` gem and the official `openfeature-sdk` dependency. The provider and base SDK deliberately share the same version, and the provider requires that exact Featurevisor version.
Use `checkout` for a flag, `checkout:variation` for its variation, and `checkout:title` for its `title` variable. Boolean variables use the boolean resolver. Arrays, hashes, and JSON variables use the object resolver.
897
+
Use `checkout` for a flag, `checkout:variation` for its variation, `checkout:title` for its `title` variable, and `variable:welcomeMessage` for a global variable. Boolean variables use the boolean resolver. Arrays, hashes, and JSON variables use the object resolver.
856
898
857
-
OpenFeature's targeting key maps to `userId` by default. `targeting_key_field`, `key_separator`, and `variation_key` can customize the mapping.
899
+
OpenFeature's targeting key maps to `userId` by default. `targeting_key_field`, `key_separator`, `variation_key`, and `global_variable_prefix` can customize the mapping. The global variable prefix defaults to `variable` and cannot contain the separator.
858
900
859
901
You can pass any Featurevisor initialization options directly to the provider. These options are used to create the Featurevisor instance owned by the provider:
860
902
@@ -908,7 +950,7 @@ The build produces `featurevisor-VERSION.gem` and `featurevisor-openfeature-VERS
908
950
- Run `bundle install`
909
951
- Push commit to `main` branch
910
952
- Wait for CI to complete
911
-
- Tag the release with the same version number, for example `v2.0.0`
953
+
- Tag the release with the same version number, for example `v3.0.0`
912
954
- The workflow verifies that the tag matches the shared version
913
955
- The workflow publishes `featurevisor` first, followed by `featurevisor-openfeature`
0 commit comments