@naturalcycles/abba 1.10.0 → 1.12.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 CHANGED
@@ -54,10 +54,10 @@ export declare class Abba {
54
54
  getAllExistingUserAssignments(userId: string): Promise<Saved<UserAssignment>[]>;
55
55
  /**
56
56
  * Generate user assignments for all active experiments.
57
- * Will return any existing and attempt to generate any new assignments.
57
+ * Will return any existing and attempt to generate any new assignments if existingOnly is false.
58
58
  * Hot method.
59
59
  */
60
- generateUserAssignments(userId: string, segmentationData: SegmentationData): Promise<GeneratedUserAssignment[]>;
60
+ generateUserAssignments(userId: string, segmentationData: SegmentationData, existingOnly?: boolean): Promise<GeneratedUserAssignment[]>;
61
61
  /**
62
62
  * Get assignment statistics for an experiment.
63
63
  * Cold method.
package/dist/abba.js CHANGED
@@ -100,13 +100,12 @@ class Abba {
100
100
  async getUserAssignment(experimentId, userId, existingOnly, segmentationData) {
101
101
  const existing = await this.getExistingUserAssignment(experimentId, userId);
102
102
  if (existing) {
103
- const experiment = await this.experimentDao.requireById(experimentId);
104
- const bucket = await this.bucketDao.getById(existing.bucketId || undefined);
105
- return {
106
- ...existing,
107
- experimentName: experiment.name,
108
- bucketKey: bucket?.key || null,
109
- };
103
+ let bucketKey = null;
104
+ if (existing.bucketId) {
105
+ const { key } = await this.bucketDao.requireById(existing.bucketId);
106
+ bucketKey = key;
107
+ }
108
+ return { ...existing, bucketKey };
110
109
  }
111
110
  if (existingOnly)
112
111
  return null;
@@ -121,7 +120,6 @@ class Abba {
121
120
  const saved = await this.userAssignmentDao.save(assignment);
122
121
  return {
123
122
  ...saved,
124
- experimentName: experiment.name,
125
123
  bucketKey: buckets.find(b => b.id === saved.bucketId)?.key || null,
126
124
  };
127
125
  }
@@ -135,34 +133,35 @@ class Abba {
135
133
  }
136
134
  /**
137
135
  * Generate user assignments for all active experiments.
138
- * Will return any existing and attempt to generate any new assignments.
136
+ * Will return any existing and attempt to generate any new assignments if existingOnly is false.
139
137
  * Hot method.
140
138
  */
141
- async generateUserAssignments(userId, segmentationData) {
139
+ async generateUserAssignments(userId, segmentationData, existingOnly = false) {
142
140
  const experiments = await this.getActiveExperiments(); // cached
143
- const existingAssignments = await this.getAllExistingUserAssignments(userId);
144
- const newAssignments = [];
145
- for (const experiment of experiments) {
146
- const existing = existingAssignments.find(ua => ua.experimentId === experiment.id);
147
- if (!existing) {
148
- const assignment = this.generateUserAssignmentData(experiment, userId, segmentationData);
149
- if (assignment) {
150
- newAssignments.push(assignment);
151
- }
152
- }
153
- }
154
- existingAssignments.push(...(await this.userAssignmentDao.saveBatch(newAssignments)));
155
141
  const assignments = [];
142
+ const newAssignments = [];
143
+ const existingAssignments = await this.getAllExistingUserAssignments(userId);
156
144
  for (const experiment of experiments) {
157
145
  const existing = existingAssignments.find(ua => ua.experimentId === experiment.id);
158
146
  if (existing) {
159
147
  assignments.push({
160
148
  ...existing,
161
- experimentName: experiment.name,
162
- bucketKey: experiment.buckets.find(i => i.id === existing.bucketId)?.key || null,
149
+ bucketKey: experiment.buckets.find(b => b.id === existing.bucketId)?.key || null,
163
150
  });
164
151
  }
152
+ else if (!existingOnly) {
153
+ const assignment = this.generateUserAssignmentData(experiment, userId, segmentationData);
154
+ if (assignment) {
155
+ const created = this.userAssignmentDao.create(assignment);
156
+ newAssignments.push(created);
157
+ assignments.push({
158
+ ...created,
159
+ bucketKey: experiment.buckets.find(b => b.id === created.bucketId)?.key || null,
160
+ });
161
+ }
162
+ }
165
163
  }
164
+ await this.userAssignmentDao.saveBatch(newAssignments);
166
165
  return assignments;
167
166
  }
168
167
  /**
@@ -13,7 +13,6 @@ CREATE TABLE IF NOT EXISTS `Bucket` (
13
13
  -- CreateTable
14
14
  CREATE TABLE IF NOT EXISTS `Experiment` (
15
15
  `id` INTEGER NOT NULL AUTO_INCREMENT,
16
- `name` VARCHAR(191) NOT NULL,
17
16
  `status` INTEGER NOT NULL,
18
17
  `sampling` INTEGER NOT NULL,
19
18
  `description` VARCHAR(240) NULL,
package/dist/types.d.ts CHANGED
@@ -4,7 +4,7 @@ export interface AbbaConfig {
4
4
  db: CommonDB;
5
5
  }
6
6
  export declare type BaseExperiment = BaseDBEntity<number> & {
7
- name: string;
7
+ id: number;
8
8
  status: number;
9
9
  sampling: number;
10
10
  description: string | null;
@@ -31,7 +31,6 @@ export declare type UserAssignment = BaseDBEntity<number> & {
31
31
  bucketId: number | null;
32
32
  };
33
33
  export declare type GeneratedUserAssignment = Saved<UserAssignment> & {
34
- experimentName: string;
35
34
  bucketKey: string | null;
36
35
  };
37
36
  export declare type SegmentationData = Record<string, string | boolean | number>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/abba",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build": "build",
package/src/abba.ts CHANGED
@@ -97,7 +97,7 @@ export class Abba {
97
97
  return {
98
98
  ...(experiment as Saved<Experiment>),
99
99
  buckets: await this.bucketDao.saveBatch(
100
- buckets.map(b => ({ ...b, experimentId: experiment.id! })),
100
+ buckets.map(b => ({ ...b, experimentId: experiment.id })),
101
101
  ),
102
102
  }
103
103
  }
@@ -150,13 +150,12 @@ export class Abba {
150
150
  const existing = await this.getExistingUserAssignment(experimentId, userId)
151
151
 
152
152
  if (existing) {
153
- const experiment = await this.experimentDao.requireById(experimentId)
154
- const bucket = await this.bucketDao.getById(existing.bucketId || undefined)
155
- return {
156
- ...existing,
157
- experimentName: experiment.name,
158
- bucketKey: bucket?.key || null,
153
+ let bucketKey = null
154
+ if (existing.bucketId) {
155
+ const { key } = await this.bucketDao.requireById(existing.bucketId)
156
+ bucketKey = key
159
157
  }
158
+ return { ...existing, bucketKey }
160
159
  }
161
160
 
162
161
  if (existingOnly) return null
@@ -179,7 +178,6 @@ export class Abba {
179
178
 
180
179
  return {
181
180
  ...saved,
182
- experimentName: experiment.name,
183
181
  bucketKey: buckets.find(b => b.id === saved.bucketId)?.key || null,
184
182
  }
185
183
  }
@@ -195,40 +193,41 @@ export class Abba {
195
193
 
196
194
  /**
197
195
  * Generate user assignments for all active experiments.
198
- * Will return any existing and attempt to generate any new assignments.
196
+ * Will return any existing and attempt to generate any new assignments if existingOnly is false.
199
197
  * Hot method.
200
198
  */
201
199
  async generateUserAssignments(
202
200
  userId: string,
203
201
  segmentationData: SegmentationData,
202
+ existingOnly = false,
204
203
  ): Promise<GeneratedUserAssignment[]> {
205
204
  const experiments = await this.getActiveExperiments() // cached
206
- const existingAssignments = await this.getAllExistingUserAssignments(userId)
207
205
 
206
+ const assignments: GeneratedUserAssignment[] = []
208
207
  const newAssignments: UserAssignment[] = []
209
- for (const experiment of experiments) {
210
- const existing = existingAssignments.find(ua => ua.experimentId === experiment.id)
211
- if (!existing) {
212
- const assignment = this.generateUserAssignmentData(experiment, userId, segmentationData)
213
- if (assignment) {
214
- newAssignments.push(assignment)
215
- }
216
- }
217
- }
218
-
219
- existingAssignments.push(...(await this.userAssignmentDao.saveBatch(newAssignments)))
208
+ const existingAssignments = await this.getAllExistingUserAssignments(userId)
220
209
 
221
- const assignments: GeneratedUserAssignment[] = []
222
210
  for (const experiment of experiments) {
223
211
  const existing = existingAssignments.find(ua => ua.experimentId === experiment.id)
224
212
  if (existing) {
225
213
  assignments.push({
226
214
  ...existing,
227
- experimentName: experiment.name,
228
- bucketKey: experiment.buckets.find(i => i.id === existing.bucketId)?.key || null,
215
+ bucketKey: experiment.buckets.find(b => b.id === existing.bucketId)?.key || null,
229
216
  })
217
+ } else if (!existingOnly) {
218
+ const assignment = this.generateUserAssignmentData(experiment, userId, segmentationData)
219
+ if (assignment) {
220
+ const created = this.userAssignmentDao.create(assignment)
221
+ newAssignments.push(created)
222
+ assignments.push({
223
+ ...created,
224
+ bucketKey: experiment.buckets.find(b => b.id === created.bucketId)?.key || null,
225
+ })
226
+ }
230
227
  }
231
228
  }
229
+
230
+ await this.userAssignmentDao.saveBatch(newAssignments)
232
231
  return assignments
233
232
  }
234
233
 
@@ -13,7 +13,6 @@ CREATE TABLE IF NOT EXISTS `Bucket` (
13
13
  -- CreateTable
14
14
  CREATE TABLE IF NOT EXISTS `Experiment` (
15
15
  `id` INTEGER NOT NULL AUTO_INCREMENT,
16
- `name` VARCHAR(191) NOT NULL,
17
16
  `status` INTEGER NOT NULL,
18
17
  `sampling` INTEGER NOT NULL,
19
18
  `description` VARCHAR(240) NULL,
package/src/types.ts CHANGED
@@ -14,7 +14,7 @@ export interface AbbaConfig {
14
14
  }
15
15
 
16
16
  export type BaseExperiment = BaseDBEntity<number> & {
17
- name: string
17
+ id: number
18
18
  status: number
19
19
  sampling: number
20
20
  description: string | null
@@ -47,7 +47,6 @@ export type UserAssignment = BaseDBEntity<number> & {
47
47
  }
48
48
 
49
49
  export type GeneratedUserAssignment = Saved<UserAssignment> & {
50
- experimentName: string
51
50
  bucketKey: string | null
52
51
  }
53
52