|
1 | 1 | # Rollout |
2 | 2 |
|
3 | | -**TODO: Add description** |
| 3 | +Rollout allows you to flip features quickly and easily. It relies on |
| 4 | +distributed erlang and uses LWW-Register and Hybrid-logical clocks |
| 5 | +to provide maximum availability. Rollout has no dependency on an external |
| 6 | +service such as redis which means rollout feature flags can be used in the |
| 7 | +critical path of a request with minimal latency increase. |
4 | 8 |
|
5 | | -## Installation |
| 9 | +* [Docs](https://hexdocs.pm/rollout). |
6 | 10 |
|
7 | | -If [available in Hex](https://hex.pm/docs/publish), the package can be installed |
8 | | -by adding `rollout` to your list of dependencies in `mix.exs`: |
| 11 | +## Installation |
9 | 12 |
|
10 | 13 | ```elixir |
11 | 14 | def deps do |
12 | 15 | [ |
13 | | - {:rollout, "~> 0.1.0"} |
| 16 | + {:rollout, "~> 0.1"} |
14 | 17 | ] |
15 | 18 | end |
16 | 19 | ``` |
17 | 20 |
|
18 | | -Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) |
19 | | -and published on [HexDocs](https://hexdocs.pm). Once published, the docs can |
20 | | -be found at [https://hexdocs.pm/rollout](https://hexdocs.pm/rollout). |
| 21 | +## Usage |
| 22 | + |
| 23 | +Rollout provides a simple api for enabling and disabling feature flags across |
| 24 | +your cluster. A feature flag can be any term. |
| 25 | + |
| 26 | +```elixir |
| 27 | +# Check if a feature is active |
| 28 | +Rollout.active?(:blog_post_comments) |
| 29 | +# => false |
| 30 | + |
| 31 | +# Activate the feature |
| 32 | +Rollout.activate(:blog_post_comments) |
| 33 | + |
| 34 | +# De-activate the feature |
| 35 | +Rollout.deactivate(:blog_post_comments) |
| 36 | +``` |
| 37 | + |
| 38 | +You can also activate a feature a certain percentage of the time. |
| 39 | + |
| 40 | +```elixir |
| 41 | +Rollout.activate_percentage(:blog_post_comments, 20) |
| 42 | +``` |
| 43 | + |
| 44 | +You can run this function on one node in your cluster and the updates will |
| 45 | +be propogated across the system. This means that updates to feature flags may |
| 46 | +not be instantaneous across the cluster but under normal conditions should propogate |
| 47 | +quickly. This is a tradeoff I've made in order to maintain the low latency when |
| 48 | +checking if a flag is enabled. |
| 49 | + |
| 50 | +## How does Rollout work? |
| 51 | + |
| 52 | +Rollout maintains a LWW Register for each flag that has been activated or |
| 53 | +deactivated. These Registers use hybrid logical clocks (HLC) for causality |
| 54 | +tracking. When a flag is activated or deactivated we update the HLC for that |
| 55 | +register and propogate that change across the cluster. When merging registers |
| 56 | +across the cluster we always take register with the latest HLC. After merging is |
| 57 | +done we store the values for each register into an ets table for fast lookups. |
| 58 | + |
| 59 | +## Caveats |
| 60 | + |
| 61 | +Rollout relies on your nodes being connected through distributed erlang. If you |
| 62 | +are running your application on more than one node and you are not clustering than |
| 63 | +your changes won't propogate. You will need to run the command on all nodes but |
| 64 | +in practice you'll probably just want to look for an alternative solution. |
| 65 | + |
| 66 | +Flags are *not* maintained in between node restarts. New nodes added to your cluster |
| 67 | +will be caught up on the current state. But if you bring up an entirely new cluster |
| 68 | +your flags will revert to their default states. You can mitigate this problem |
| 69 | +by setting defaults for each flag in your `Application.start/2` callback. |
| 70 | + |
| 71 | +Because we're using CRDTs to propogate changes its possible that a change made |
| 72 | +on one node will take time to propogate to the other nodes. Its a safe operation |
| 73 | +to run the same operation on multiple nodes. When feature flags are merged we |
| 74 | +also default to the latest HLC. |
| 75 | + |
| 76 | +## Should I use this? |
| 77 | + |
| 78 | +For now I'd say "No". The functionality works but this repo currently has 0 |
| 79 | +tests and I'm sure there are edge cases. You should also not cluster your |
| 80 | +application for the sole purpose of using this library. If you need this |
| 81 | +you'll know it. Otherwise you're better off looking at an alternative solution. |
| 82 | + |
| 83 | +## Future work |
| 84 | + |
| 85 | +I'd like to implement an alternative storage engine for use in non-clustered |
| 86 | +environments, preferably using a fast storage engine such as redis. If anyone |
| 87 | +wants to submit that PR I'd love to take a look at it. |
21 | 88 |
|
0 commit comments