@naturalcycles/abba 1.18.5 → 1.19.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/dist/abba.d.ts +6 -1
- package/dist/abba.js +7 -0
- package/dist/util.d.ts +5 -5
- package/dist/util.js +1 -1
- package/package.json +3 -3
- package/src/abba.ts +13 -2
- package/src/util.ts +6 -6
package/dist/abba.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Unsaved } from '@naturalcycles/js-lib';
|
|
1
2
|
import { AbbaConfig, Bucket, Experiment, ExperimentAssignmentStatistics, ExperimentWithBuckets, GeneratedUserAssignment } from './types';
|
|
2
3
|
import { SegmentationData } from '.';
|
|
3
4
|
export declare class Abba {
|
|
@@ -11,6 +12,10 @@ export declare class Abba {
|
|
|
11
12
|
* Cached (see CACHE_TTL)
|
|
12
13
|
*/
|
|
13
14
|
getAllExperiments(): Promise<ExperimentWithBuckets[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Updates all user assignments with a given userId with the provided userId.
|
|
17
|
+
*/
|
|
18
|
+
updateUserId(oldId: string, newId: string): Promise<void>;
|
|
14
19
|
/**
|
|
15
20
|
* Returns all experiments.
|
|
16
21
|
*/
|
|
@@ -24,7 +29,7 @@ export declare class Abba {
|
|
|
24
29
|
* Update experiment information, will also validate the buckets' ratio if experiment.active is true
|
|
25
30
|
* Cold method.
|
|
26
31
|
*/
|
|
27
|
-
saveExperiment(experiment: Experiment, buckets: Bucket[]): Promise<ExperimentWithBuckets>;
|
|
32
|
+
saveExperiment(experiment: Experiment, buckets: Unsaved<Bucket>[]): Promise<ExperimentWithBuckets>;
|
|
28
33
|
/**
|
|
29
34
|
* Ensures that mutual exclusions are maintained
|
|
30
35
|
*/
|
package/dist/abba.js
CHANGED
|
@@ -27,6 +27,13 @@ class Abba {
|
|
|
27
27
|
async getAllExperiments() {
|
|
28
28
|
return await this.getAllExperimentsNoCache();
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Updates all user assignments with a given userId with the provided userId.
|
|
32
|
+
*/
|
|
33
|
+
async updateUserId(oldId, newId) {
|
|
34
|
+
const query = this.userAssignmentDao.query().filterEq('userId', oldId);
|
|
35
|
+
await this.userAssignmentDao.updateByQuery(query, { userId: newId });
|
|
36
|
+
}
|
|
30
37
|
/**
|
|
31
38
|
* Returns all experiments.
|
|
32
39
|
*/
|
package/dist/util.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Unsaved } from '@naturalcycles/js-lib';
|
|
2
2
|
import { Bucket, ExclusionSet, Experiment, ExperimentWithBuckets, SegmentationData, SegmentationRule, SegmentationRuleFn, SegmentationRuleOperator, UserAssignment } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Generate a new assignment for a given user.
|
|
@@ -12,15 +12,15 @@ export declare const rollDie: () => number;
|
|
|
12
12
|
/**
|
|
13
13
|
* Determines a users assignment for this experiment. Returns null if they are not considered to be in the sampling group
|
|
14
14
|
*/
|
|
15
|
-
export declare const determineAssignment: (sampling: number, buckets:
|
|
15
|
+
export declare const determineAssignment: (sampling: number, buckets: Bucket[]) => Bucket | null;
|
|
16
16
|
/**
|
|
17
17
|
* Determines which bucket a user assignment will recieve
|
|
18
18
|
*/
|
|
19
|
-
export declare const determineBucket: (buckets:
|
|
19
|
+
export declare const determineBucket: (buckets: Bucket[]) => Bucket;
|
|
20
20
|
/**
|
|
21
21
|
* Validate the total ratio of the buckets equals 100
|
|
22
22
|
*/
|
|
23
|
-
export declare const validateTotalBucketRatio: (buckets: Bucket[]) => void;
|
|
23
|
+
export declare const validateTotalBucketRatio: (buckets: Unsaved<Bucket>[]) => void;
|
|
24
24
|
/**
|
|
25
25
|
* Validate a users segmentation data against multiple rules. Returns false if any fail
|
|
26
26
|
*
|
|
@@ -36,7 +36,7 @@ export declare const segmentationRuleMap: Record<SegmentationRuleOperator, Segme
|
|
|
36
36
|
/**
|
|
37
37
|
* Returns true if an experiment is able to generate new assignments based on status and start/end dates
|
|
38
38
|
*/
|
|
39
|
-
export declare const canGenerateNewAssignments: (experiment:
|
|
39
|
+
export declare const canGenerateNewAssignments: (experiment: Experiment, exclusionSet: ExclusionSet) => boolean;
|
|
40
40
|
/**
|
|
41
41
|
* Returns an object that includes keys of all experimentIds a user should not be assigned to
|
|
42
42
|
* based on a combination of existing assignments and mutual exclusion configuration
|
package/dist/util.js
CHANGED
|
@@ -124,7 +124,7 @@ exports.segmentationRuleMap = {
|
|
|
124
124
|
const canGenerateNewAssignments = (experiment, exclusionSet) => {
|
|
125
125
|
return (!exclusionSet.has(experiment.id) &&
|
|
126
126
|
experiment.status === types_1.AssignmentStatus.Active &&
|
|
127
|
-
|
|
127
|
+
js_lib_1.localDate.today().isBetween(experiment.startDateIncl, experiment.endDateExcl, '[)'));
|
|
128
128
|
};
|
|
129
129
|
exports.canGenerateNewAssignments = canGenerateNewAssignments;
|
|
130
130
|
/**
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/abba",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@naturalcycles/db-lib": "^9.1
|
|
9
|
-
"@naturalcycles/js-lib": "^14.
|
|
8
|
+
"@naturalcycles/db-lib": "^9.14.1",
|
|
9
|
+
"@naturalcycles/js-lib": "^14.237.0",
|
|
10
10
|
"@naturalcycles/nodejs-lib": "^13.1.3",
|
|
11
11
|
"semver": "^7.3.5"
|
|
12
12
|
},
|
package/src/abba.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _assert, _Memo, _shuffle, pMap } from '@naturalcycles/js-lib'
|
|
1
|
+
import { _assert, _Memo, _shuffle, pMap, Unsaved } from '@naturalcycles/js-lib'
|
|
2
2
|
import { LRUMemoCache } from '@naturalcycles/nodejs-lib'
|
|
3
3
|
import { bucketDao } from './dao/bucket.dao'
|
|
4
4
|
import { experimentDao } from './dao/experiment.dao'
|
|
@@ -43,6 +43,14 @@ export class Abba {
|
|
|
43
43
|
return await this.getAllExperimentsNoCache()
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Updates all user assignments with a given userId with the provided userId.
|
|
48
|
+
*/
|
|
49
|
+
async updateUserId(oldId: string, newId: string): Promise<void> {
|
|
50
|
+
const query = this.userAssignmentDao.query().filterEq('userId', oldId)
|
|
51
|
+
await this.userAssignmentDao.updateByQuery(query, { userId: newId })
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
/**
|
|
47
55
|
* Returns all experiments.
|
|
48
56
|
*/
|
|
@@ -85,7 +93,10 @@ export class Abba {
|
|
|
85
93
|
* Update experiment information, will also validate the buckets' ratio if experiment.active is true
|
|
86
94
|
* Cold method.
|
|
87
95
|
*/
|
|
88
|
-
async saveExperiment(
|
|
96
|
+
async saveExperiment(
|
|
97
|
+
experiment: Experiment,
|
|
98
|
+
buckets: Unsaved<Bucket>[],
|
|
99
|
+
): Promise<ExperimentWithBuckets> {
|
|
89
100
|
if (experiment.status === AssignmentStatus.Active) {
|
|
90
101
|
validateTotalBucketRatio(buckets)
|
|
91
102
|
}
|
package/src/util.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Unsaved, localDate } from '@naturalcycles/js-lib'
|
|
2
2
|
import { satisfies } from 'semver'
|
|
3
3
|
import {
|
|
4
4
|
AssignmentStatus,
|
|
@@ -44,7 +44,7 @@ export const rollDie = (): number => {
|
|
|
44
44
|
/**
|
|
45
45
|
* Determines a users assignment for this experiment. Returns null if they are not considered to be in the sampling group
|
|
46
46
|
*/
|
|
47
|
-
export const determineAssignment = (sampling: number, buckets:
|
|
47
|
+
export const determineAssignment = (sampling: number, buckets: Bucket[]): Bucket | null => {
|
|
48
48
|
// Should this person be considered for the experiment?
|
|
49
49
|
if (rollDie() > sampling) {
|
|
50
50
|
return null
|
|
@@ -57,7 +57,7 @@ export const determineAssignment = (sampling: number, buckets: Saved<Bucket>[]):
|
|
|
57
57
|
/**
|
|
58
58
|
* Determines which bucket a user assignment will recieve
|
|
59
59
|
*/
|
|
60
|
-
export const determineBucket = (buckets:
|
|
60
|
+
export const determineBucket = (buckets: Bucket[]): Bucket => {
|
|
61
61
|
const bucketRoll = rollDie()
|
|
62
62
|
let range: [number, number] | undefined
|
|
63
63
|
const bucket = buckets.find(b => {
|
|
@@ -82,7 +82,7 @@ export const determineBucket = (buckets: Saved<Bucket>[]): Bucket => {
|
|
|
82
82
|
/**
|
|
83
83
|
* Validate the total ratio of the buckets equals 100
|
|
84
84
|
*/
|
|
85
|
-
export const validateTotalBucketRatio = (buckets: Bucket[]): void => {
|
|
85
|
+
export const validateTotalBucketRatio = (buckets: Unsaved<Bucket>[]): void => {
|
|
86
86
|
const bucketSum = buckets.reduce((sum, current) => sum + current.ratio, 0)
|
|
87
87
|
if (bucketSum !== 100) {
|
|
88
88
|
throw new Error('Total bucket ratio must be 100 before you can activate an experiment')
|
|
@@ -141,13 +141,13 @@ export const segmentationRuleMap: Record<SegmentationRuleOperator, SegmentationR
|
|
|
141
141
|
* Returns true if an experiment is able to generate new assignments based on status and start/end dates
|
|
142
142
|
*/
|
|
143
143
|
export const canGenerateNewAssignments = (
|
|
144
|
-
experiment:
|
|
144
|
+
experiment: Experiment,
|
|
145
145
|
exclusionSet: ExclusionSet,
|
|
146
146
|
): boolean => {
|
|
147
147
|
return (
|
|
148
148
|
!exclusionSet.has(experiment.id) &&
|
|
149
149
|
experiment.status === AssignmentStatus.Active &&
|
|
150
|
-
|
|
150
|
+
localDate.today().isBetween(experiment.startDateIncl, experiment.endDateExcl, '[)')
|
|
151
151
|
)
|
|
152
152
|
}
|
|
153
153
|
|