Skip to content

Commit 2a86bff

Browse files
committed
refactor event processor
1 parent 1d814a2 commit 2a86bff

File tree

66 files changed

+1517
-1393
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1517
-1393
lines changed

lib/core/decision_service/index.tests.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ import {
2525
DECISION_SOURCES,
2626
} from '../../utils/enums';
2727
import { createLogger } from '../../plugins/logger';
28-
import { createForwardingEventProcessor } from '../../plugins/event_processor/forwarding_event_processor';
28+
import { getForwardingEventProcessor } from '../../event_processor/forwarding_event_processor';
2929
import { createNotificationCenter } from '../notification_center';
3030
import Optimizely from '../../optimizely';
3131
import OptimizelyUserContext from '../../optimizely_user_context';
3232
import projectConfig, { createProjectConfig } from '../../project_config/project_config';
3333
import AudienceEvaluator from '../audience_evaluator';
3434
import errorHandler from '../../plugins/error_handler';
35-
import eventDispatcher from '../../plugins/event_dispatcher/index.node';
35+
import eventDispatcher from '../../event_processor/default_dispatcher.browser';
3636
import * as jsonSchemaValidator from '../../utils/json_schema_validator';
3737
import { getMockProjectConfigManager } from '../../tests/mock/mock_project_config_manager';
3838

@@ -1075,7 +1075,7 @@ describe('lib/core/decision_service', function() {
10751075
jsonSchemaValidator: jsonSchemaValidator,
10761076
isValidInstance: true,
10771077
logger: createdLogger,
1078-
eventProcessor: createForwardingEventProcessor(eventDispatcher),
1078+
eventProcessor: getForwardingEventProcessor(eventDispatcher),
10791079
notificationCenter: createNotificationCenter(createdLogger, errorHandler),
10801080
errorHandler: errorHandler,
10811081
});

lib/core/event_builder/build_event_v1.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
EventTags,
1818
ConversionEvent,
1919
ImpressionEvent,
20-
} from '../../modules/event_processor';
20+
} from '../../event_processor';
2121

2222
import { Event } from '../../shared_types';
2323

lib/core/event_builder/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
import { LoggerFacade } from '../../modules/logging';
17-
import { EventV1 as CommonEventParams } from '../../modules/event_processor';
17+
import { EventV1 as CommonEventParams } from '../../event_processor';
1818

1919
import fns from '../../utils/fns';
2020
import { CONTROL_ATTRIBUTES, RESERVED_EVENT_KEYWORDS } from '../../utils/enums';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { vi, expect, it, describe, afterAll } from 'vitest';
2+
3+
vi.mock('./default_dispatcher', () => {
4+
const DefaultEventDispatcher = vi.fn();
5+
return { DefaultEventDispatcher };
6+
});
7+
8+
vi.mock('../utils/http_request_handler/browser_request_handler', () => {
9+
const BrowserRequestHandler = vi.fn();
10+
return { BrowserRequestHandler };
11+
});
12+
13+
import { DefaultEventDispatcher } from './default_dispatcher';
14+
import { BrowserRequestHandler } from '../utils/http_request_handler/browser_request_handler';
15+
import eventDispatcher from './default_dispatcher.browser';
16+
17+
describe('eventDispatcher', () => {
18+
afterAll(() => {
19+
MockDefaultEventDispatcher.mockReset();
20+
MockBrowserRequestHandler.mockReset();
21+
});
22+
const MockBrowserRequestHandler = vi.mocked(BrowserRequestHandler);
23+
const MockDefaultEventDispatcher = vi.mocked(DefaultEventDispatcher);
24+
25+
it('creates and returns the instance by calling DefaultEventDispatcher', () => {
26+
expect(Object.is(eventDispatcher, MockDefaultEventDispatcher.mock.instances[0])).toBe(true);
27+
});
28+
29+
it('users a BrowserRequestHandler', () => {
30+
expect(Object.is(eventDispatcher, MockDefaultEventDispatcher.mock.instances[0])).toBe(true);
31+
expect(Object.is(MockDefaultEventDispatcher.mock.calls[0][0], MockBrowserRequestHandler.mock.instances[0])).toBe(true);
32+
});
33+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright 2016-2017, 2020-2022, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { BrowserRequestHandler } from "../utils/http_request_handler/browser_request_handler";
18+
import { EventDispatcher } from '../event_processor';
19+
import { DefaultEventDispatcher } from './default_dispatcher';
20+
21+
const eventDispatcher: EventDispatcher = new DefaultEventDispatcher(new BrowserRequestHandler());
22+
23+
export default eventDispatcher;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { vi, expect, it, describe, afterAll } from 'vitest';
2+
3+
vi.mock('./default_dispatcher', () => {
4+
const DefaultEventDispatcher = vi.fn();
5+
return { DefaultEventDispatcher };
6+
});
7+
8+
vi.mock('../utils/http_request_handler/node_request_handler', () => {
9+
const NodeRequestHandler = vi.fn();
10+
return { NodeRequestHandler };
11+
});
12+
13+
import { DefaultEventDispatcher } from './default_dispatcher';
14+
import { NodeRequestHandler } from '../utils/http_request_handler/node_request_handler';
15+
import eventDispatcher from './default_dispatcher.node';
16+
17+
describe('eventDispatcher', () => {
18+
const MockNodeRequestHandler = vi.mocked(NodeRequestHandler);
19+
const MockDefaultEventDispatcher = vi.mocked(DefaultEventDispatcher);
20+
21+
afterAll(() => {
22+
MockDefaultEventDispatcher.mockReset();
23+
MockNodeRequestHandler.mockReset();
24+
})
25+
26+
it('creates and returns the instance by calling DefaultEventDispatcher', () => {
27+
expect(Object.is(eventDispatcher, MockDefaultEventDispatcher.mock.instances[0])).toBe(true);
28+
});
29+
30+
it('users a NodeRequestHandler', () => {
31+
expect(Object.is(eventDispatcher, MockDefaultEventDispatcher.mock.instances[0])).toBe(true);
32+
expect(Object.is(MockDefaultEventDispatcher.mock.calls[0][0], MockNodeRequestHandler.mock.instances[0])).toBe(true);
33+
});
34+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Copyright 2016-2018, 2020-2021, 2024 Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import { EventDispatcher } from '../event_processor';
17+
import { NodeRequestHandler } from '../utils/http_request_handler/node_request_handler';
18+
import { DefaultEventDispatcher } from './default_dispatcher';
19+
20+
const eventDispatcher: EventDispatcher = new DefaultEventDispatcher(new NodeRequestHandler());
21+
22+
export default eventDispatcher;
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { expect, vi, describe, it } from 'vitest';
2+
import { DefaultEventDispatcher } from './default_dispatcher';
3+
import { EventV1 } from '../event_processor';
4+
5+
const getEvent = (): EventV1 => {
6+
return {
7+
account_id: 'string',
8+
project_id: 'string',
9+
revision: 'string',
10+
client_name: 'string',
11+
client_version: 'string',
12+
anonymize_ip: true,
13+
enrich_decisions: false,
14+
visitors: [],
15+
};
16+
};
17+
18+
describe('DefaultEventDispatcher', () => {
19+
it('reject the response promise if the eventObj.httpVerb is not POST', async () => {
20+
const eventObj = {
21+
url: 'https://cdn.com/event',
22+
params: getEvent(),
23+
httpVerb: 'GET' as const,
24+
};
25+
26+
const requestHnadler = {
27+
makeRequest: vi.fn().mockReturnValue({
28+
abort: vi.fn(),
29+
responsePromise: Promise.resolve({ statusCode: 203 }),
30+
}),
31+
};
32+
33+
const dispatcher = new DefaultEventDispatcher(requestHnadler);
34+
await expect(dispatcher.dispatchEvent(eventObj)).rejects.toThrow();
35+
});
36+
37+
it('sends correct headers and data to the requestHandler', async () => {
38+
const eventObj = {
39+
url: 'https://cdn.com/event',
40+
params: getEvent(),
41+
httpVerb: 'POST' as const,
42+
};
43+
44+
const requestHnadler = {
45+
makeRequest: vi.fn().mockReturnValue({
46+
abort: vi.fn(),
47+
responsePromise: Promise.resolve({ statusCode: 203 }),
48+
}),
49+
};
50+
51+
const dispatcher = new DefaultEventDispatcher(requestHnadler);
52+
await dispatcher.dispatchEvent(eventObj);
53+
54+
expect(requestHnadler.makeRequest).toHaveBeenCalledWith(
55+
eventObj.url,
56+
{
57+
'content-type': 'application/json',
58+
'content-length': JSON.stringify(eventObj.params).length.toString(),
59+
},
60+
'POST',
61+
JSON.stringify(eventObj.params)
62+
);
63+
});
64+
65+
it('returns a promise that resolves with correct value if the response of the requestHandler resolves', async () => {
66+
const eventObj = {
67+
url: 'https://cdn.com/event',
68+
params: getEvent(),
69+
httpVerb: 'POST' as const,
70+
};
71+
72+
const requestHnadler = {
73+
makeRequest: vi.fn().mockReturnValue({
74+
abort: vi.fn(),
75+
responsePromise: Promise.resolve({ statusCode: 203 }),
76+
}),
77+
};
78+
79+
const dispatcher = new DefaultEventDispatcher(requestHnadler);
80+
const response = await dispatcher.dispatchEvent(eventObj);
81+
82+
expect(response.statusCode).toEqual(203);
83+
});
84+
85+
it('returns a promise that rejects if the response of the requestHandler rejects', async () => {
86+
const eventObj = {
87+
url: 'https://cdn.com/event',
88+
params: getEvent(),
89+
httpVerb: 'POST' as const,
90+
};
91+
92+
const requestHnadler = {
93+
makeRequest: vi.fn().mockReturnValue({
94+
abort: vi.fn(),
95+
responsePromise: Promise.reject(new Error('error')),
96+
}),
97+
};
98+
99+
const dispatcher = new DefaultEventDispatcher(requestHnadler);
100+
await expect(dispatcher.dispatchEvent(eventObj)).rejects.toThrow();
101+
});
102+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
import { RequestHandler } from '../utils/http_request_handler/http';
3+
import { EventDispatcher, EventDispatcherResponse, EventV1Request } from '../event_processor';
4+
5+
export class DefaultEventDispatcher implements EventDispatcher {
6+
private requestHandler: RequestHandler;
7+
8+
constructor(requestHandler: RequestHandler) {
9+
this.requestHandler = requestHandler;
10+
}
11+
12+
async dispatchEvent(
13+
eventObj: EventV1Request
14+
): Promise<EventDispatcherResponse> {
15+
// Non-POST requests not supported
16+
if (eventObj.httpVerb !== 'POST') {
17+
return Promise.reject(new Error('Only POST requests are supported'));
18+
}
19+
20+
const dataString = JSON.stringify(eventObj.params);
21+
22+
const headers = {
23+
'content-type': 'application/json',
24+
'content-length': dataString.length.toString(),
25+
};
26+
27+
const abortableRequest = this.requestHandler.makeRequest(eventObj.url, headers, 'POST', dataString);
28+
return abortableRequest.responsePromise;
29+
}
30+
}

lib/modules/event_processor/eventDispatcher.ts renamed to lib/event_processor/eventDispatcher.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@
1616
import { EventV1 } from "./v1/buildEventV1";
1717

1818
export type EventDispatcherResponse = {
19-
statusCode: number
19+
statusCode?: number
2020
}
2121

22-
export type EventDispatcherCallback = (response: EventDispatcherResponse) => void
23-
2422
export interface EventDispatcher {
25-
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void
23+
dispatchEvent(event: EventV1Request): Promise<EventDispatcherResponse>
2624
}
2725

2826
export interface EventV1Request {

0 commit comments

Comments
 (0)