Andrew Fontaine

Mostly code

Unleash and Elixir… and GitLab

24 Aug 2019

I’ve been a GitLab member for 3 years now, but became a GitLab staff member in January 2019. It’s be a whirlwind year so far. Working for a hot startup moving at this pace has been the biggest change I’ve had to experience since moving to Ontario. It’s been exciting and wonderful, but that’s tangential to what this is about. At GitLab, I work on the release team, and a big area I focus on is FEATURE FLAGS!

Feature Flags… what

Feature flags, if you haven’t had the opportunity, can be a big part of continuous delivery. Martin Fowler loves them, and GitHub Actions featured them.

At GitLab, our feature flag implementation is compatible with Unleash, and we are compatible with any of the clients that support unleash. However, my favourite functional language wasn’t compatible! There was no unleash-client-elixir, but after 7 months of learning the deep intricacies of feature flags and working up the courage to actually release something, there is!

unleash_ex

This is my first elixir project that has made it to any sort of usable state. I’ve been trying to build a few phoenix applications as I come up with ideas for them, but learning phoenix AND elixir (and brushing up on my general backend skills) was a tad overwhelming, so unleash gave me something simple to focus on and get my language basics down.

There are well-kept docs for specifications, so I thankfully didn’t have to implement things blindly or reverse-engineering another client implementation. There are also client specification tests that can be implemented to give me confidence that my code was correct.

Design

This has given me some good digging into what makes a great elixir library, and about what the ecosystem brings to the table, including the glorious OTP.

OTP Goodness

An OTP application starts that will poll the configured server for feature flags. A GenServer starts to maintain the state of the feature flags as received from the server, and one starts to capture metrics, sending them periodically.

Extension

Each strategy is implemented in its own module, using a module that adds some logging around the check as well as ensuring the strategy implements the interface correctly. A tuple of the pattern {result, map} is expected, the map contains relevant details, computed or otherwise, to be logged out. An example:

defmodule MyApp.MyStrategy do
  use Unleash.Strategy

  def enabled?(params, context) do
    # do work
    {true, params}
  end

end

An example map from userWithId that is used to put relevant details in logging:

%{user_id_list: list, user_id: user_id}

This results in a log line of the following:

UserWithId computed true from user_id_list: 1,2,3, user_id: 2

By comparison, if a simple true/false is returned, the log line is simply:

UserWithId computed true

That doesn’t really doesn’t tell anyone much, so I strongly encourage the first use.

To use your new strategy, you must configure the library to use a new module that can list all the available strategies, including yours:

defmodule MyApp.Strategies do
  @behaviour Unleash.Strategy

  def strategies do
    [{"myStrategy", MyApp.MyStrategy}] ++ Unleash.Strategies.strategies()
  end
end


# config.exs

config :unleash, Unleash, strategies: MyApp.Strategies

Improvements

As with all things software, “finished” isn’t exactly a state of any project. There are a few tasks that I think would improve use of the project:

  1. Move away from Config.
    • Config and Mix.Config count as an anti-pattern when building a library, even though only 1 instance of unleash shold probably be used per application.
    • I’m thinking of injecting configuration through application initialization, and probably storing that in an Agent for easy retrevial later.
  2. Write more tests.
    • While 9 is nothing to scoff at (64% at the time of writing, hopefully it’s gone up since then), I can do better, and there are some areas that I’m very unsure about. The GenServer and OTP areas, specifically.
  3. Keep up to date with Unleash.
    • Unleash itself is a moving project, so I’ve signed up to keeping up with it. I can’t promise to be fast, but I can try my best!

I feedback. Let me know what you think of this article on Twitter @afontaine_ca