[Suggestion] Gauging interest for allowing more datatypes within a flag
kieraneglin opened this issue · 2 comments
We have a case where we'd like the ability to toggle a numeric range as a flag. While this isn't purely a feature flag, it has overlap with FWF in the sense that we need a UI to edit values at runtime. A hypothetical API could look like this:
FunWithFlags.enable(:high_quality_threshold, values: %{
enabled_value: 10..25,
disabled_value: 0..0
})
FunWithFlags.enabled?(:high_quality_threshold) # true
FunWithFlags.value(:high_quality_threshold) # 10..25
FunWithFlags.disable(:high_quality_threshold)
FunWithFlags.enabled?(:high_quality_threshold) # false
FunWithFlags.value(:high_quality_threshold) # 0..0
This hasn't been fully thought through with regards to how this would interact with actors, gates etc. Furthermore, any type aside from booleans, strings, ints, and nil may be out of scope for an initial attempt.
We're likely going to be building this functionality on top of FWF for our own purposes, but I'd like to know if there would be interest in a PR for this feature with the intent of getting it in the base library/UI library. If so, I'd also like to hear any thoughts you may have on API design.
Hi, thank you for using the package and for opening this issue.
I think I understand the use case, and I think it's cool that in theory FunWithFlags could support this. I assume that you're interested in the combination of persistent store, ETS cache, pubsub for broadcasting changes and web/Elixir UI.
However, this seems too specific a use case for FunWithFlags, and I would not be inclined to add it to the library, I'm sorry. As you point out, also, we'd have to understand how this would interact with the current gate hierarchy. Another reason is that while I know that some feature flag systems support storing complex values (i.e. LaunchDarkly), I'm not a big fan of that approach. I like my flags to be simple, and to push more complex behaviours to the application layer.
A couple of suggestions.
If you don't need to change the 10..25
range at runtime, then you could implement this on top of FunWithFlags without any changes. Just use a normal boolean gate, and query it in a function to decide which value should be returned.
If you really want to customize the range, then an alternative is to heavily abuse the percentage gates to store and retrieve numbers in the range 0..1
(floats, so 0..100000000000):
# Store the values.
FunWithFlags.enable(:my_store_low_limit, for_percentage_of: {:actors, 0.1})
FunWithFlags.enable(:my_store_high_limit, for_percentage_of: {:actors, 0.25})
# Retrieve the values.
%{gates: [%{for: val_low}]} = FunWithFlags.get_flag(:my_store_low_limit)
%{gates: [%{for: val_high}]} = FunWithFlags.get_flag(:my_store_high_limit)
# Use them to build a range.
range = (val_low * 100 |> trunc)..(val_high * 100 |> trunc)
# 10..25
It's not really how they're meant to be used, but that API is stable so it should be ok.
Thank you for the thoughtful reply! We'll keep looking around and see what options are best for our needs.