NAME

Toggle - Feature toggles (a.k.a. flippers, flags, switches etc.)

SYNOPSIS

use Redis;
use Toggle;

# This probably happens once for your application, e.g. via Bread::Board
my $redis = Redis->new;
my $toggle = Toggle->new( storage => $redis );

# Define any groups you might need - your sub will be passed the $user
# object that you send to is_active(), and should return true/false.
$toggle->define_group( staff => sub {
    my $user = shift;
    return $user->has_role('staff');
});

...

# In your controllers

# $user must have an ->id accessor
if ( $toggle->is_active(chat => $user) ) {
    # Show this user the shiny new chat feature
}

...

# Elsewhere, in a management UI tool
$toggle->activate_user( chat => $bob );      # Turn it on for Bob
$toggle->activate_group( chat => 'staff' );  # Enable staff testing
$toggle->activate_percentage( chat => 10 );  # 10% rollout

DESCRIPTION

Toggle lets you activate features for different users, storing this configuration in a database like Redis. You can use it to roll out your code to a percentage of users, or specific users/groups that you define.

METHODS

new

Constructor.

my $toggle = Toggle->new( storage => $store );

The storage attribute must be an object that supports get($key), set($key, $value) and del($key) methods. This happens to be the same interface that Redis uses, but you could make your own.

is_active

Check whether a feature is active. This is the method which you would expect to use all the time in your application code. Can be called in two ways - either to check whether a feature is active for everyone:

$toggle->is_active( 'chat' );

or to check whether it is enabled for a particular user:

$toggle->is_active( chat => $user );

In the second case, the $user object must have an id accessor.

activate

Enable a feature for everyone.

$toggle->activate( 'chat' );

deactivate

Disable a feature for everyone. Useful if you discover a critical bug and want to turn it off altogether. Overrides all the user/group/percentage activations that may have been on previously.

$toggle->deactivate( 'chat' );

define_group

You may wish to use this method to define groups for use below in "activate_group". You pass a subroutine which will accept a single argument (the $user object given to "is_active") and will return a boolean to say whether the user is in the group.

$toggle->define_group( admins => sub { shift->is_an_admin() } );

The group 'all' is defined by default.

$toggle->define_group( all => sub { 1 } );

activate_group

Turn on a feature for a group. The group must have been defined previously (see "define_group"), or be the "all" group.

$toggle->activate_group( chat => 'admins' );

deactivate_group

Turn off a feature for a group. The group must have been defined previously using "define_group".

$toggle->deactivate_group( chat => 'admins' );

Note that any users which have been explicitly enabled via "activate_user" will still be able to see the feature, even if they are in the group.

activate_user

Turn on a feature for an individual user.

$toggle->activate_user( chat => $user );

deactivate_user

Turn off a feature for an individual user.

$toggle->deactivate_user( chat => $user );

activate_percentage

Activate a feature for a percentage of users, such as for an incremental rollout of a new feature.

$toggle->activate_percentage( chat => 10 );

The algorithm used is CRC32( $user->id ) % 100 < percentage, so as the percentage increases, users do not fall out of the group.

Note that activating the feature for 100% of users will activate the feature globally (i.e. when "is_active" is called without a $user argument).

deactivate_percentage

Deactivate a feature for all users that were receiving an incremental rollout.

$toggle->deactivate_percentage( 'chat' );

Note that users who were previously activated individually or as part of a group will still have the feature active.

features

List all the features that the storage knows about.

my @features = $toggle->features();

add_feature

Add a feature to the storage, but do not activate it for anyone.

$toggle->add_feature( 'chat' );

remove_feature

Remove a feature from the storage.

$toggle->remove_feature( 'chat' );

This will disable it for all users, and will also stop it appearing in the output of "features".

SEE ALSO

Github repo: https://github.com/cv-library/Toggle

Inspired/shamelessly ported from https://github.com/FetLife/rollout

COPYRIGHT

Copyright © 2014 CV-Library Ltd.

Licensed under the same terms as Perl 5.