Molasses

Build StatusCoverage Status

A feature toggle library using redis or SQL (using Ecto) as a backing service. It allows you to roll out to users based on a percentage. Alternatively, you can use Molasses to deploy to a group of users or user ids.

Installation

  1. Add molasses to your list of dependencies in mix.exs and run mix deps.get:
```elixir
def deps do
  [{:molasses, "~> 0.2.0"}]
end
```
  1. Install related dependencies by including ExRedis, MongoDB or Ecto and one of its adapter libraries for Postgres or Mysql.
2A. Redis

For Redis, you will just need to include `exredis`:

```elixir
def deps do
  [
    {:molasses, "~> 0.2.0"},
    {:exredis, ">= 0.2.4"}
  ]
end
```

2B. SQL using Ecto

For Ecto with PostgreSQL, install `ecto` and `postgrex`. You will also need to start ecto and postgrex as applications:

```elixir
def deps do
  [
    {:molasses, "~> 0.2.0"},
    {:ecto, "~> 2.1.1"},
    {:postgrex, ">= 0.0.0"}
  ]
end

def application do
  [applications: [:ecto, :postgrex]]
end
```

Your config will also need to change. You will need to set up an Ecto Repo like you would [here](https://hexdocs.pm/ecto/Ecto.html#module-repositories). As well as set the Molasses adapter to postgres.

```elixir
# molasses adapter setting
config :molasses, adapter: "ecto"
```

You will need to create an ecto migration and add the features tables.

```elixir

    defmodule Repo.CreateTestMocks do
      use Ecto.Migration

      def change do
        create table(:features) do
          add :name, :string
          add :percentage, :integer
          add :users, :string
          add :active, :boolean
        end

        create index(:features, [:name])
      end
    end
 ```

2C. MongoDB

```elixir
def deps do
  [
    {:molasses, "~> 0.2.0"},
    {:mongodb, ">= 0.0.0"},
  ]
end
```

For a working example of how to set up Molasses look at [Molasses Example](https://github.com/securingsincity/molasses-example)

Usage

Molasses uses the same interface whether you are using Redis or SQL. Each function takes an Ecto.Repo or the ExRedis client as the first argument.

Activate

Deactivate

Checking to see if a feature is active

Examples

Redis


# Create a new redis client
{:ok, client} = Exredis.start_link

# activate a feature
Molasses.activate(client, "my_feature")

# activate a feature for a percentage of users
Molasses.activate(client, "my_feature", 75)

# activate a feature for a subset of integer based userIds
Molasses.activate(client, "my_feature", [2, 4, 5])

# activate a feature for a subset of string based userIds (think a mongoId) or a list of groups
Molasses.activate(client, "my_feature", ["admins", "super admins"])

# activate a feature for only one group of users
Molasses.activate(client, "my_feature", "powerusers")

# checking if a feature is active for all users
Molasses.is_active(client, "my_feature")

# checking if a feature is active for a specific user (based on percentage, or user id/group)
Molasses.is_active(client, "my_feature", identifier)

# deactivate a feature
Molasses.deactivate(client, "my_feature")

Ecto

# Switched to ecto as my adapter
Application.put_env(:molasses,:adapter, "ecto")

# alias the Repo for use
alias Molasses.Test.Repo

# use is_active and activate the same way but it uses the Ecto repo instead of
Molasses.activate(Repo, "my_feature", 75)
Molasses.is_active(Repo, "my_feature")

MongoDB

# Switched to ecto as my adapter
Application.put_env(:molasses,:adapter, "mongo")


# Create a new mongo client
{:ok, conn} = Mongo.start_link(database: "molasses")


# use is_active and activate the same way but it uses the Ecto repo instead of
Molasses.activate(conn, "my_feature", 75)
Molasses.is_active(conn, "my_feature")