@featurevisor/core 0.14.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/traffic.js CHANGED
@@ -1,111 +1,122 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNewTraffic = void 0;
3
+ exports.getTraffic = exports.detectIfRangesChanged = exports.getRulePercentageDiff = exports.detectIfVariationsChanged = void 0;
4
4
  var sdk_1 = require("@featurevisor/sdk");
5
- function getNewTraffic(
5
+ var allocator_1 = require("./allocator");
6
+ function detectIfVariationsChanged(yamlVariations, // as exists in latest YAML
7
+ existingFeature) {
8
+ if (!existingFeature) {
9
+ return false;
10
+ }
11
+ return (JSON.stringify(existingFeature.variations.map(function (_a) {
12
+ var value = _a.value, weight = _a.weight;
13
+ return ({
14
+ value: value,
15
+ weight: weight,
16
+ });
17
+ })) !== JSON.stringify(yamlVariations.map(function (_a) {
18
+ var value = _a.value, weight = _a.weight;
19
+ return ({ value: value, weight: weight });
20
+ })));
21
+ }
22
+ exports.detectIfVariationsChanged = detectIfVariationsChanged;
23
+ function getRulePercentageDiff(trafficPercentage, // 0 to 100k
24
+ existingTrafficRule) {
25
+ if (!existingTrafficRule) {
26
+ return 0;
27
+ }
28
+ var existingPercentage = existingTrafficRule.percentage;
29
+ return trafficPercentage - existingPercentage;
30
+ }
31
+ exports.getRulePercentageDiff = getRulePercentageDiff;
32
+ function detectIfRangesChanged(availableRanges, // as exists in latest YAML
33
+ existingFeature) {
34
+ if (!existingFeature) {
35
+ return false;
36
+ }
37
+ if (!existingFeature.ranges) {
38
+ return false;
39
+ }
40
+ return JSON.stringify(existingFeature.ranges) !== JSON.stringify(availableRanges);
41
+ }
42
+ exports.detectIfRangesChanged = detectIfRangesChanged;
43
+ function getTraffic(
6
44
  // from current YAML
7
45
  variations, parsedRules,
8
46
  // from previous release
9
- existingFeature) {
47
+ existingFeature,
48
+ // ranges from group slots
49
+ ranges) {
10
50
  var result = [];
11
- parsedRules.forEach(function (parsedRollout) {
12
- var rolloutPercentage = parsedRollout.percentage;
51
+ // @TODO: may be pass from builder directly?
52
+ var availableRanges = ranges && ranges.length > 0 ? ranges : [{ start: 0, end: sdk_1.MAX_BUCKETED_NUMBER }];
53
+ parsedRules.forEach(function (parsedRule) {
54
+ var rulePercentage = parsedRule.percentage; // 0 - 100
13
55
  var traffic = {
14
- key: parsedRollout.key,
15
- segments: typeof parsedRollout.segments !== "string"
16
- ? JSON.stringify(parsedRollout.segments)
17
- : parsedRollout.segments,
18
- percentage: rolloutPercentage * (sdk_1.MAX_BUCKETED_NUMBER / 100),
56
+ key: parsedRule.key,
57
+ segments: typeof parsedRule.segments !== "string"
58
+ ? JSON.stringify(parsedRule.segments)
59
+ : parsedRule.segments,
60
+ percentage: rulePercentage * (sdk_1.MAX_BUCKETED_NUMBER / 100),
19
61
  allocation: [],
20
62
  };
21
- if (parsedRollout.variables) {
22
- traffic.variables = parsedRollout.variables;
63
+ // overrides
64
+ if (parsedRule.variables) {
65
+ traffic.variables = parsedRule.variables;
23
66
  }
24
- if (parsedRollout.variation) {
25
- traffic.variation = parsedRollout.variation;
67
+ if (parsedRule.variation) {
68
+ traffic.variation = parsedRule.variation;
26
69
  }
27
- var existingTrafficRollout = existingFeature === null || existingFeature === void 0 ? void 0 : existingFeature.traffic.find(function (t) { return t.key === parsedRollout.key; });
28
- // @TODO: handle if Variations changed (added/removed, or weight changed)
29
- // - new variation added
30
- // - variation removed
31
- // - variation weight changed
32
- //
33
- // make it better by maintaining as much of the previous bucketing as possible
34
- var variationsChanged = existingFeature
35
- ? JSON.stringify(existingFeature.variations.map(function (_a) {
36
- var value = _a.value, weight = _a.weight;
37
- return ({
38
- value: value,
39
- weight: weight,
40
- });
41
- })) !== JSON.stringify(variations.map(function (_a) {
42
- var value = _a.value, weight = _a.weight;
43
- return ({ value: value, weight: weight });
44
- }))
45
- : false;
46
- var diffPercentage = 0;
47
- if (existingTrafficRollout) {
48
- diffPercentage =
49
- rolloutPercentage - existingTrafficRollout.percentage / (sdk_1.MAX_BUCKETED_NUMBER / 100);
50
- if (diffPercentage > 0 &&
51
- !variationsChanged // if variations changed, we need to re-bucket
52
- ) {
53
- // increase: build on top of existing allocations
54
- traffic.allocation = existingTrafficRollout.allocation.map(function (_a) {
55
- var variation = _a.variation, percentage = _a.percentage;
56
- return {
57
- variation: variation,
58
- percentage: percentage,
59
- };
60
- });
61
- }
70
+ // detect changes
71
+ var variationsChanged = detectIfVariationsChanged(variations, existingFeature);
72
+ var existingTrafficRule = existingFeature === null || existingFeature === void 0 ? void 0 : existingFeature.traffic.find(function (t) { return t.key === parsedRule.key; });
73
+ var rulePercentageDiff = getRulePercentageDiff(traffic.percentage, existingTrafficRule);
74
+ var rangesChanged = detectIfRangesChanged(availableRanges, existingFeature);
75
+ var needsRebucketing = !existingTrafficRule || // new rule
76
+ variationsChanged || // variations changed
77
+ rulePercentageDiff <= 0 || // percentage decreased
78
+ rangesChanged; // belongs to a group, and group ranges changed
79
+ var updatedAvailableRanges = JSON.parse(JSON.stringify(availableRanges));
80
+ var lastEnd = 0;
81
+ if (existingTrafficRule && !needsRebucketing) {
82
+ // increase: build on top of existing allocations
83
+ var existingSum_1 = 0;
84
+ traffic.allocation = existingTrafficRule.allocation.map(function (_a) {
85
+ var variation = _a.variation, percentage = _a.percentage, // @TODO: remove it in next breaking semver
86
+ range = _a.range;
87
+ var result = {
88
+ variation: variation,
89
+ percentage: percentage,
90
+ range: range || {
91
+ start: lastEnd,
92
+ end: percentage,
93
+ },
94
+ };
95
+ existingSum_1 += percentage || 0;
96
+ lastEnd = lastEnd + (percentage || 0);
97
+ return result;
98
+ });
99
+ updatedAvailableRanges = (0, allocator_1.getUpdatedAvailableRangesAfterFilling)(availableRanges, existingSum_1);
62
100
  }
63
101
  variations.forEach(function (variation) {
64
- var newPercentage = parseInt(((variation.weight / 100) *
65
- rolloutPercentage *
66
- (sdk_1.MAX_BUCKETED_NUMBER / 100)).toFixed(2));
67
- if (!existingTrafficRollout || variationsChanged === true) {
68
- traffic.allocation.push({
69
- variation: variation.value,
70
- percentage: newPercentage,
71
- });
72
- return;
73
- }
74
- // const prevTotalWeightForVariation = existingTrafficRollout.allocation
75
- // .filter((a) => a.variation === variation.value)
76
- // .reduce((acc, curr) => acc + curr.percentage, 0);
77
- // const diffWeightForVariation = (variation.weight as number) - prevTotalWeightForVariation / (MAX_BUCKETED_NUMBER / 100));
78
- if (diffPercentage === 0) {
79
- // no change
80
- traffic.allocation.push({
81
- variation: variation.value,
82
- percentage: newPercentage,
83
- });
84
- return;
85
- }
86
- if (diffPercentage > 0) {
87
- // increase - need to consistently bucket
88
- traffic.allocation.push({
89
- variation: variation.value,
90
- percentage: parseInt((variation.weight *
91
- (diffPercentage / 100) *
92
- (sdk_1.MAX_BUCKETED_NUMBER / 100)).toFixed(2)),
93
- });
94
- return;
95
- }
96
- if (diffPercentage < 0) {
97
- // decrease - need to re-bucket
98
- // @TODO: can we maintain as much pre bucketed values as possible? to be close to consistent bucketing?
102
+ var weight = variation.weight;
103
+ var percentage = weight * (sdk_1.MAX_BUCKETED_NUMBER / 100);
104
+ var toFillValue = needsRebucketing
105
+ ? percentage * (rulePercentage / 100) // whole value
106
+ : (weight / 100) * rulePercentageDiff; // incrementing
107
+ var rangesToFill = (0, allocator_1.getAllocation)(updatedAvailableRanges, toFillValue);
108
+ rangesToFill.forEach(function (range) {
99
109
  traffic.allocation.push({
100
110
  variation: variation.value,
101
- percentage: newPercentage,
111
+ percentage: toFillValue,
112
+ range: range,
102
113
  });
103
- return;
104
- }
114
+ });
115
+ updatedAvailableRanges = (0, allocator_1.getUpdatedAvailableRangesAfterFilling)(updatedAvailableRanges, toFillValue);
105
116
  });
106
117
  result.push(traffic);
107
118
  });
108
119
  return result;
109
120
  }
110
- exports.getNewTraffic = getNewTraffic;
121
+ exports.getTraffic = getTraffic;
111
122
  //# sourceMappingURL=traffic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"traffic.js","sourceRoot":"","sources":["../src/traffic.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"traffic.js","sourceRoot":"","sources":["../src/traffic.ts"],"names":[],"mappings":"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"}