Skip to content

Commit

Permalink
feat: Add new Flexible Rollout Strategy (#517)
Browse files Browse the repository at this point in the history
* feat: Add new Flexible Rollout Strategy

fixes #516

* feat: update unleash-frontend to version 3.2.8

* chore: update flexible rollout documentation
  • Loading branch information
ivarconr committed Oct 24, 2019
1 parent 3a88a1a commit 80c08c0
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 5 deletions.
14 changes: 14 additions & 0 deletions docs/activation-strategies.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ Active for users with a `userId` defined in the `userIds` list. Typically I want

- userIds - _List of user IDs you want the feature toggle to be enabled for_

## flexibleRollout

A flexible rollout strategy which combines all gradual rollout strategies in to a single strategy (and will in time replace them). This strategy have different options for how you want to handle the stickiness, and have sane default mode.

**Parameters**

- **stickiness** is used to define how we guarantee consistency for gradual rollout. The same userId and the same rollout percentage should give predictable results. Configuration that should be supported:
- **DEFAULT** - Unleash chooses the first value present on the context in defined order userId, sessionId, random.
- **USERID** - guaranteed to be sticky on userId. If userId not present the behaviour would be false
- **SESSIONID - **guaranteed to be sticky on sessionId. If sessionId not present the behaviour would be false.
- **RANDOM** - no stickiness guaranteed. For every isEnabled call it will yield a random true/false based on the selected rollout percentage.
- **groupId** is used to ensure that different toggles will **hash differently** for the same user. The groupId defaults to _feature toggle name_, but is overridable by the user to _correlate rollout_ of multiple feature toggles.
- **rollout** The percentage (0-100) you want to enable the feature toggle for.

## gradualRolloutUserId

The `gradualRolloutUserId` strategy gradually activates a feature toggle for logged in users. Stickiness is based on the user ID. The strategy guarantees that the same user gets the same experience every time across devices. It also assures that a user which is among the first 10% will also be among the first 20% of the users. That way, we ensure the users get the same experience, even if we gradually increase the number of users exposed to a particular feature. To achieve this, we hash the user ID and normalise the hash value to a number between 1 and 100 with a simple modulo operator.
Expand Down
64 changes: 64 additions & 0 deletions migrations/20191023184858-flexible-rollout-strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict';

const flexibleRollout = require('./flexible-rollout-strategy.json');
const async = require('async');

function insertStrategySQL(strategy) {
return `
INSERT INTO strategies (name, description, parameters, built_in)
SELECT '${strategy.name}', '${strategy.description}', '${JSON.stringify(
strategy.parameters
)}', 1
WHERE
NOT EXISTS (
SELECT name FROM strategies WHERE name = '${strategy.name}'
);`;
}

function insertEventsSQL(strategy) {
return `
INSERT INTO events (type, created_by, data)
SELECT 'strategy-created', 'migration', '${JSON.stringify(strategy)}'
WHERE
NOT EXISTS (
SELECT name FROM strategies WHERE name = '${strategy.name}'
);`;
}

function removeEventsSQL(strategy) {
return `
INSERT INTO events (type, created_by, data)
SELECT 'strategy-deleted', 'migration', '${JSON.stringify(strategy)}'
WHERE
EXISTS (
SELECT name FROM strategies WHERE name = '${
strategy.name
}' AND built_in = 1
);`;
}

function removeStrategySQL(strategy) {
return `
DELETE FROM strategies
WHERE name = '${strategy.name}' AND built_in = 1`;
}

exports.up = function(db, callback) {
async.series(
[
db.runSql.bind(db, insertEventsSQL(flexibleRollout)),
db.runSql.bind(db, insertStrategySQL(flexibleRollout)),
],
callback
);
};

exports.down = function(db, callback) {
async.series(
[
db.runSql.bind(db, removeEventsSQL(flexibleRollout)),
db.runSql.bind(db, removeStrategySQL(flexibleRollout)),
],
callback
);
};
24 changes: 24 additions & 0 deletions migrations/flexible-rollout-strategy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "flexibleRollout",
"description": "Gradually activate feature toggle based on sane stickiness",
"parameters": [
{
"name": "rollout",
"type": "percentage",
"description": "",
"required": false
},
{
"name": "stickiness",
"type": "string",
"description": "Used define stickiness. Possible values: default, userId, sessionId, random",
"required": true
},
{
"name": "groupId",
"type": "string",
"description": "Used to define a activation groups, which allows you to correlate across feature toggles.",
"required": true
}
]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"prometheus-gc-stats": "^0.6.1",
"response-time": "^2.3.2",
"serve-favicon": "^2.5.0",
"unleash-frontend": "3.2.7",
"unleash-frontend": "3.2.8",
"yargs": "^14.0.0"
},
"devDependencies": {
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5906,10 +5906,10 @@ universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"

unleash-frontend@3.2.7:
version "3.2.7"
resolved "https://registry.yarnpkg.com/unleash-frontend/-/unleash-frontend-3.2.7.tgz#ec2af024229589d2f070e6961de65bb063375b40"
integrity sha512-30fZKazTiPbTL2335T6B0EBjQbqezlZ/wb9OFGSIjIA6S14/9+5hL9qx6E6V2dCtX0FX32pGGXnSrjuzq2on7Q==
unleash-frontend@3.2.8:
version "3.2.8"
resolved "https://registry.yarnpkg.com/unleash-frontend/-/unleash-frontend-3.2.8.tgz#b8dedc23d3c44cac313c6da617940b5ea5162b83"
integrity sha512-QeXWOE+nxtumZYOyt9KZsIVpnaQPgEibAsvGhsS0t8ZidSnUybPbY/NE82IDOVneKO34kwfRCTnIkiQQLc4EEw==

unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
Expand Down

0 comments on commit 80c08c0

Please sign in to comment.