Skip to content

Add event-processor package #239

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

Merged
merged 12 commits into from
Mar 12, 2019
Merged

Conversation

jordangarcia
Copy link
Contributor

@jordangarcia jordangarcia commented Mar 4, 2019

Summary

  • This adds the js-sdk-event-processor packages to the main repo.

Integration into the optimizely-sdk package will occur in a later PR.

Test plan

  • Unit tests

@coveralls
Copy link

coveralls commented Mar 4, 2019

Coverage Status

Coverage remained the same at 97.649% when pulling 4bc292d on jordan/add-event-processor-package into 066b99d on master.


layer: {
id: string
} | null
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This shouldn't be null ever really.

Do we want to use campaign here?

key: event.key,
},

revenue: getRevenueValue(eventTags),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we just let strings pass through here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

use regex to verify that it's a number only.

always send as a string

[key: string]: string | number | null
}

export function buildConversionEvent(opts: {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this appears to be unused in the integration of event-processor

Copy link
Contributor Author

Choose a reason for hiding this comment

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

move all of these functions out to decision-service for now

)
return null
}
return parsed
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Dont return the parsed value here, return the unparsed (could be string)

)
return null
}
return parsed
Copy link
Contributor Author

Choose a reason for hiding this comment

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

same as above, return unparsed.

}) {
this.dispatcher = dispatcher

const factory = eventQueueFactory || new DefaultEventQueueFactory()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

do we need the queue to be replaceable

}

enqueue(event: K): void {
this.buffer.push(event)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

start the timer only after the first event is put in

// loop and apply all transformers
for (let transformer of this.transformers) {
try {
await transformer(event, projectConfig)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we give them a wrapper / interface to do mutation on here

What are the things they'd want to change:

  1. set user attribute
  2. set event

Copy link
Contributor

@mjc1283 mjc1283 left a comment

Choose a reason for hiding this comment

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

LGTM. Really great code. Left some comments to consider, but I approve regardless.

  • I don't understand why you want to add the models package in this PR. It's substantial amount of code that, from what I can tell, isn't even necessary right now (only used by transformers and interceptors, which are placeholders and not exposed for real use). I would suggest removing the package (or just keeping only Managed in it), then we can add it and review it separately. But I still tried to give models a thorough review anyway.
  • In general I though it was best to avoid using the any type, unless there was truly no other option, but if you don't agree I'd like to understand why.


describe('eventQueue', () => {
beforeEach(() => {
jest.useFakeTimers()
Copy link
Contributor

Choose a reason for hiding this comment

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

Weird, I would have thought you want to call jest.useRealTimers in afterEach to restore real timers. Does resetAllMocks restore real timers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good catch. It's not actually using the real timers ever here.

For the test it doesn't really need to use real timers.

I'm not sure how jest works between running different files (if they are run in the same global context). But i'll add a useRealTimers in afterEach here.

queue.stop()
})

it('should flush the queue and invoke clearInterval', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: this test description doesn't seem to match what the test is doing.

localCallback(true)
})

it('should return a promise that is resolved when the dispatcher callback fires false', done => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused, this test seems very similar to the previous one. What's the difference when the dispatcher fires false instead of true?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is testing the processor.stop() functionality.

This test is saying that even if the request fails to send but the dispatcher yielded control back, then the .stop() promise should be resolved

event: EventV1,
}

export interface HttpEventDispatcher extends EventDispatcher {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why extends EventDispatcher?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's ensuring this interface defined in HttpEventDispatcher is still a valid EventDispatcher

export type EventTransformer = (
event: ProcessableEvents,
projectConfig: ProjectConfig,
) => Promise<any>
Copy link
Contributor

Choose a reason for hiding this comment

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

Should it be Promise<void> instead of Promise<any>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably should.

Once it's compiled this wont be enforced at all, but in TypeScript land you probably shouldn't be returning anything here.

})
}

start(): void {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is having the start method on the EventQueue type pointless?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It implements Managed. Yes in this instance having a start method is pointless. But for us to use the type Managed and have other parts of the system only know about Managed it needs to implement a no-op

[userId: string]: string // variationId
}

type ExperimentStatus = 'Running' | 'Launched' | 'Paused' | 'Not started'
Copy link
Contributor

Choose a reason for hiding this comment

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

When would you use a union of strings like this, vs. an enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I dont have a great answer to this, they both have drawbacks.

An enum is probably better here, as it's easier to not make a typing mistake when comparing it

@jordangarcia jordangarcia force-pushed the jordan/add-event-processor-package branch from f86000d to 74cc1bd Compare March 11, 2019 20:47
@jordangarcia jordangarcia changed the title Add event-processor and models packages Add event-processor package Mar 11, 2019
@jordangarcia jordangarcia merged commit 553e6ff into master Mar 12, 2019
@mikeproeng37 mikeproeng37 deleted the jordan/add-event-processor-package branch June 4, 2020 20:57
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.

3 participants