quarantine v0.1.1 Quarantine

Quarantine

Quarantine is a tiny OTP application for feature toggles.

Currently it supports two strategies:

  • whitelist list of ids that can access some feature
  • percentage compute a score from the given id check with score <= percentage. Note that the combination of feature name and id produce a deterministic score

Setup

Add quarantine to your application deps

def deps do
  [
    {:quarantine, "~> 0.1.0"}
  ]
end

You can setup flags using config environment or provide a Quarantine.Driver to fetch configuration from an external source

When hardcoded config is good enough you can provide it as below

config :quarantine, 
   some_percentage_flag: 0.5,
   some_whitelist_flag: [1, 2, 3]
   other_whitelist_flag: ["08362804-bdc0-11e8-9407-24750000045e", "9fbc6c6e-f2dd-4f9d-8944-b81dd5a25fed"]

Usage

Simply call enabled?/2 where you want to split the control flow

Quarantine.enabled?(:some_percentage_flag, 1)
=> false

Quarantine.enabled?(:some_percentage_flag, 2)
=> true

Quarantine.enabled?(:some_whitelist_flag, 1)
=> true

Quarantine.enabled?(:some_whitelist_flag, 9)
=> false

When using percentage you can check current ids distribution if needed with scores/2

Quarantine.scores(:some_percentage_flag, [1, 2, 3])
=>  [{1, 0.9967498283360037},
     {2, 0.18811322194247349},
     {3, 0.30522621499961855}]

Testing

Flags can be enabled for a specific test with Quarantine.Server.start_link/1.

Quarantine.Server.start_link(feature1: [1], feature2: [3,4])

Refresh config without re-deploying your application

To do that you should provide an implementation of Quarantine.Driver that fetch flags configuration from a external source

Redis Driver example:

defmodule RedisDriver do
  @behaviour Quarantine.Driver

  def get_flags() do
    Redix.command!(:my_redix, ["GET", "my_flags"])
  end
end

S3 Driver example:

defmodule S3Driver do
  @behaviour Quarantine.Driver

  def get_flags() do
    "bucket"
    |> ExAws.S3.get_object("path")
    |> ExAws.request!()
  end
end

Then add it to :quarantine configuration:

config :quarantine, 
   driver: RedisDriver,
   poll_interval: 60_000 # in ms

Link to this section Summary

Functions

Check if the given feature is enabled or disabled for the given id

Compute the scores of the given feature for the ids

Link to this section Types

Link to this type feature_name()
feature_name() :: atom() | String.t()

Link to this section Functions

Link to this function enabled?(feature, id)
enabled?(feature_name(), id()) :: boolean()

Check if the given feature is enabled or disabled for the given id.

Returns true or false.

Examples

iex> Quarantine.enabled?(:some_feature, 1) false

Link to this function scores(feature, ids)
scores(feature_name(), id()) :: float()

Compute the scores of the given feature for the ids.

Returns float between 0.0 and 1.0

Examples

iex> Quarantine.scores(:some_feature, [10, 11]) [{10, 0.21571679255359733}, {11, 0.7114824139772641}]

iex> Quarantine.scores(:other_feature, [10, 11]) [{10, 0.7513847562371252}, {11, 0.9227740901808195}]