Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Auto-assignment tracking #22

Merged
merged 11 commits into from
Aug 8, 2023
Merged

feat: Auto-assignment tracking #22

merged 11 commits into from
Aug 8, 2023

Conversation

tyiuhc
Copy link
Collaborator

@tyiuhc tyiuhc commented Jul 17, 2023

Summary

Added auto-assignment tracking feature

Checklist

  • Does your PR title have the correct title format?
  • Does your PR have a breaking change?: No

@tyiuhc tyiuhc requested a review from bgiori July 17, 2023 16:46
@tyiuhc tyiuhc changed the title Auto-assignment tracking feat: auto-assignment tracking Jul 17, 2023
@tyiuhc tyiuhc changed the title feat: auto-assignment tracking feat: Auto-assignment tracking Jul 17, 2023
Copy link
Collaborator

@bgiori bgiori left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will review again once other changes are in

@@ -23,8 +23,8 @@ export type Variants = {

export type FlagResult = {
value: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload: any | null | undefined;
payload: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has payload been converted to a string here?

Copy link
Collaborator

@bgiori bgiori left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work Tim! Lets meet on Monday to go over these review comments.

Comment on lines 15 to 16
let sb =
this.user.user_id?.trim() + ' ' + this.user.device_id?.trim() + ' ';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You can use a template string to start with, and you should use a different variable name, sb is used in java due to the StringBuilder class which is not used in javascript. I would prefer:

Suggested change
let sb =
this.user.user_id?.trim() + ' ' + this.user.device_id?.trim() + ' ';
let canonical = `${this.user.user_id?.trim()} ${this.user.device_id?.trim()} `;

this.user.user_id?.trim() + ' ' + this.user.device_id?.trim() + ' ';
for (const key of Object.keys(this.results).sort()) {
const value = this.results[key];
sb += key.trim() + ' ' + value?.value?.trim() + ' ';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use template string here.

Comment on lines 25 to 31
export interface AssignmentService {
track(assignment: Assignment): Promise<void>;
}

export interface AssignmentFilter {
shouldTrack(assignment: Assignment): boolean;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolute super minor nit: I prefer interface definitions at the top of the file :)

import { DAY_MILLIS } from 'src/assignment/assignment-service';
import { Cache } from 'src/util/cache';

export const DEFAULT_FILTER_CAPACITY = 65536;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you're just transcribing my code, so this is really my fault, but: Remove this default from this file, set the default in a DefaultAssignmentConfiguration object in the config.ts file. Then object spread the input with the defaults (as we do with the base configuration) in local evaluation client constructor.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import { sleep } from 'src/util/time';
import { MockAssignmentFilter } from 'test/local/util/mockAssignmentFilter';

test('filter - single assignment', async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm skimming the tests, just note:
Please add more tests if you don't understand some part of the code and want to make sure it's doing what you expect

You will have to fix all the bugs that eventually make it into production :)

import { Assignment, AssignmentFilter } from 'src/assignment/assignment';
import { Cache } from 'src/util/cache';

export class MockAssignmentFilter implements AssignmentFilter {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why we need an explicit mock class not just using jest?

});
await client.start();
await client.evaluate({ user_id: 'tim.yiu@amplitude.com' });
await sleep(4000);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the purpose of these 4000 sleeps?

const client = new LocalEvaluationClient(apiKey, {});
await client.start();
await client.evaluate({ user_id: 'tim.yiu@amplitude.com' });
await sleep(4000);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the purpose of these 4000 sleeps?

packages/node/src/util/cache.ts Show resolved Hide resolved
Tim Yiu added 2 commits July 31, 2023 09:58
Copy link
Collaborator

@bgiori bgiori left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks awesome 🥇

Couple of comments, please implement assignment filtering and export the new config before merging.

};

export type AssignmentConfiguration = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to export this & NodeOptions in the index.ts file.

@@ -85,6 +113,7 @@ export class LocalEvaluationClient {
this.flags,
);
const results: Results = evaluation.evaluate(this.flags, user);
void this.assignmentService?.track(new Assignment(user, results));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter results before passing to track.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, last thing, we always want to include flags with type mutual-exclusion-group or holdout-group in the assignment.

This is a bit of a hack until we add topological sorting before evaluation in this SDK also :)

@tyiuhc tyiuhc merged commit 6866739 into main Aug 8, 2023
@tyiuhc tyiuhc deleted the assignment-tracking-2 branch August 8, 2023 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants