View Source Changelog
Unreleased
3.0.0
WARNING: BREAKING CHANGE Users relying on propagated overrides for variants will be affected by this update.
Highlights
- Updated get_variant/2 to support the official Unleash API's strategy variants while maintaining compatibility with feature variants.
- API interface remains unchanged.
- Removed support for propagated overrides for variants.
Details
The official Unleash API has deprecated feature variants in favor of strategy variants. We've adapted our implementation to align with this change while ensuring backward compatibility.
Why we removed propagated overrides for variants
- Supporting propagated overrides for strategy variants would require knowledge of the specific strategy where each variant is defined.
- This would significantly complicate both the overrides header schema and implementation.
- The existing implementation for feature variants overrides lacked robust support for creating overrides with payloads.
This architectural decision balances API modernization with maintaining a clean implementation.
2.1.0
- Restore Fresha-specific behaviour of automatically populating a custom
context property
"namespace"
from the environment variableUNLEASH_NAMESPACE
. - Remove references to Mojito. It has been swapped out for Req in version 1.10.0.
2.0.0 - 2024-08-15
Highlights
New API & Upgrade Guide
WARNING: BREAKING CHANGES!
The main APIs of the SDK have been restructured for safety, clarity and expressiveness,
and the main utilities to do feature checks are now the two macros enabled?/2
and get_variant/2
,
which feature a keyword-based call signature.
Old usage:
Unleash.enabled?(:my_flag)
# Second argument here is the "default" (fallback if feature is missing)
Unleash.enabled?("another_flag", false)
# Second argument here is the context that gets passed to feature activation strategy evaluation
Unleash.enabled?(:flag_three, %{user_id: "user-123"})
# 3-arity clause
Unleash.enabled?("flag_four", %{}, true)
New usage:
# You have to require the `Unleash.Macros` module.
# In this example we alias it to `Unleash` to make it nicer, but you do you.
require Unleash.Macros, as: Unleash
Unleash.enabled?(:my_flag)
# Explicit named arguments avoid ambiguous calls and allow extra
# options to be introduced in the future.
Unleash.enabled?("another_flag", fallback: false)
Unleash.enabled?(:flag_three, context: %{user_id: "user-123"})
# Note that you can pass the keyword arguments in any order
Unleash.enabled?("flag_four", fallback: true, context: %{})
# Overrides have to be explicitly allowed when evaluating a feature or they will be ignored.
Unleash.enabled?("flag_five", fallback: nil, allow_overrides: true)
The macros allow us to check at compile-time what options are provided and emit compilation warnings in case of unsupported ones, and do other compile-time checks to ensure the clarity and correctness of feature flags checks. Additionally, by using the macros you can swap out the underlying runtime implementation, for example to use a mock one in tests. See the updated README.
Note that this means the names (not values!) of the parameters must be passed as compile-time constants. This is not valid:
def my_function(feature_check_options) do
# Opts is a local variable at compile-time
Unleash.enabled?(:some_flag, feature_check_options)
end
# Opts is an expression at compile time
Unleash.enabled?(:some_flag, if(some_condition(), do: [], else: [fallback: ]))
But don't worry, you're very unlikely to incur in this case in normal usage. Even if you do, you will get a helpful compilation error explaining the problem and how to address it.
In edge cases where you can't use the macros, which should be quite unlikely,
you can use directly the equivalent functions in Unleash.Runtime
.
Added
- Two new macros
Unleash.Macros.enabled?/1,2
andUnleash.Macros.get_variant/1,2
, which are now the main methods to check a feature flag. - the
Unleash
module now defines a behaviour for Runtime implementations. This can be used to define Mox/Hammox mocks and, combined with the next point, facilitates testing. See the testing section on the README. - the actual runtime implementation (and
Application
) has been moved toUnleash.Runtime
. The Runtime can be swapped via compile-time config.
Changed
- It is now possible to pass
nil
as a fallback value toenabled?/2
andget_variant/2
, which allows you to customise how you handle missing feature flags. - For extra safety, overrides are now "opt-in".
You have to explicitly tell Unleash to consider them, when checking for a feature/variant,
by passing the option
allow_overrides: true
. - The
find_in_context/2
function has been moved toUnleash.Context.find/2
.
Removed
- The following functions have been removed:
Unleash.is_enabled/1,2,3
Unleash.enabled?/1,2,3
Unleash.get_variant/1,2,3
Improved
- Improved documentation and tests throughout
- Improved type specs
- Updated and reworded README.
1.16.0 - 2024-08-08
Highlights
gRPC Interceptors
This release introduces gRPC interceptors that seamlessly enable the propagation mechanism within your gRPC-based applications.
It includes four interceptors:
Unleash.Propagation.GRPC.ContextServerInterceptor
Unleash.Propagation.GRPC.ContextClientInterceptor
Unleash.Propagation.GRPC.ImpressionsServerInterceptor
Unleash.Propagation.GRPC.ImpressionsClientInterceptor
The first two interceptors are responsible for the propagation of context and overrides.
The server interceptor automatically extracts the incoming Unleash context and feature overrides,
which are then considered during feature evaluations within the context of request handling.
The client interceptor propagates context and overrides further when invoking downstream gRPC services.
The latter two interceptors handle the propagation of feature impressions.
The server interceptor initiates an impressions tracking session during request handling and automatically returns the generated impressions when sending the gRPC response.
Meanwhile, the client interceptor reads impressions returned by downstream gRPC services and merges them with the locally generated impressions.
Added
- gRPC interceptors for the Propagation mechanism.
Fixed
- Changes to test setup helpers which should strongly reduce the flakiness of the tests.
1.15.0 - 2024-08-06
Highlights
Impression Tracking
This release introduces a new propagation mechanism to track impressions generated within a tracking session, which typically corresponds to a logical execution unit, such as a request handler. These tracked impressions can be retrieved, for instance, to be sent back to the caller in a response header.
It includes a new Plug, track_impression/2
, which can be seamlessly integrated into your router or pipeline
to handle this process for you.
Added
- Impressions tracking core functionality:
Unleash.Propagation.track_impressions/0
,Unleash.Propagation.record_impression/2
,Unleash.Propagation.impressions/0
- Impressions tracking Plug:
Unleash.Propagation.Plugs.track_impressions/1,2
1.14.0 - 2024-07-29
Add
Unleash.Propagation.Serialization.serialize_context!/1
andUnleash.Propagation.Serialization.serialize_overrides!/1
.These new methods can be invoked by users of the SDK to futher propagate context and overrides when sending requests to downstream services.
1.13.0 - 2024-07-29
Introduce the Propagation mechanism
The propagation mechanism allows to set overrides and context values that will be considered whenever a feature state is evaluated (via
enabled/3
orget_variant/3
) in the current or descendant processes. The SDK includes two new Plugs that can be used in your Plug-based application to automatically extracts overrides and context out of incoming HTTP request headers and store them in the Propagation mechanism.Support for both string keys and atom keys in context
properties
.Previously the SDK would expect a context's
:properties
field to be a map with atom keys. (though this expectation wasn't enforced nor specified anywhere).With the new propagation mechanism, arbitrary properties can be set from HTTP requests. The SDK stores them as string keys instead of doing a potentially dangerous runtime conversion of dynamic data to atoms.
This is a potentially breaking change if your application relied on properties with string values being ignored by the SDK (which is unlikely).
A new function
Unleash.find_in_context/2
has been introduced to consistently lookup values in a context, which handles fallback to:properties
and the string/atom dichotomy.
1.12.0 - 2024-07-23
- Tune retry behaviour of HTTP requests to Unleash API server.
They are now only retried once after 50ms, instead of the default
Req
behaviour of retrying 3 times after 1s, 2s, 4s. - Silence warnings on
Req
retries. - Log an error when failing to contact the Unleash API server (after retry).
1.11.0 - 2024-07-19
- Avoid failing and crashing in case of missing or invalid bootstrap/backup file.
- Load bootstrap/backup file synchronously on startup.
- Do not read the backup file on server errrors. Keep using the local cache instead, which we assume to be in-sync with the backup file, as they bot get udpated whenever we obtain fresh features from the server.
1.10.2 - 2024-06-19
- Add
namespace
to context
1.10.1 - 2024-06-19
- Fix caseInsensitve
1.10.0 - 2024-05-20
- replace Mojito with Req
1.9.2 - 2023-01-25
- Update dependencies
- Add version, date, number comparison
1.9.0 - 2023-01-25
- add: Telemetry events for
Unleash.Client
!28 - add: Telemetry events for
Unleash.enabled?
!29 - add: Telemetry events for
Unleash.get_variant
!30 - add: Telemetry events for
Unleash.Repo
!31 - add: Telemetry events for metrics pushed to server !33
- remove: Logger calls !37
Thanks Jekri Orlina and Sam Hutchings for telemetry adoption.
1.8.3 - 2022-05-31
- fix: Avoid crash when mojito connect is closed for the metrics client !26 Thanks John Bell!
- fix: Feature flag without variants cause FunctionClause Error !25 Thanks Ulisses Almeida
1.8.2
- fix
Unleash.Metrics.add_metrics
ccrash for unrecorded feature_toggle !24 Thanks calvin-kargo!
1.8.1
- fix Unleash.Metrics to provide proper start_link/1 behaviour !23 Thanks calvinsadewa!
1.8.0
- Use ETS cache to store features rather than Genserver state !22 Thanks Maximilien Rothier Bautzer
1.7.2
- Disabled flags should not produce an active variant !20 Thanks Daniel Cooper
1.7.1
- Handle unexpected mojito_response messages !19 Thanks Daniel Cooper
1.7.0
- Also transform the member in a list query !17 Thanks Daniel Cooper!
- Update mojito to current !18 Thanks Daniel Cooper!
1.6.0
- Add Flexible Rollout Strategy !12
- Support Constraints for Feature Flags !14
- Avoid using Mix.env at runtime !16 Thanks Daniel Cooper!
1.5.0
- Add ability to fetch all feature flag names decfa826
1.4.1
- Suport Running With Distillery !10 Thanks Thomas Chandler!
- Use cached features when unexpected response received from Unleash server !11 Thanks Thomas Chandler!
1.4.0
- Add Support for Capturing Metrics on Variants !7
1.3.1
- Fix Missing Content-Type for Posting Metrics 89d073cf
1.3.0
1.2.0
1.1.0
1.0.0
- Implement Client Specification Tests !4
0.2.0
- Add E-Tag Caching Support !1
- Send the Library Version when Registering Client !2
- Add Checks for a Retry Limit !3
0.1.0
- Initial release