Skip to content

Commit cfcdb73

Browse files
authored
fix(events): Fix two event ingestion bugs (#175)
1 parent 3eb5ce4 commit cfcdb73

File tree

3 files changed

+28
-18
lines changed

3 files changed

+28
-18
lines changed

src/events/default-event-dispatcher.spec.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const createDispatcher = (
2828
retryIntervalMs: 300,
2929
maxRetryDelayMs: 5000,
3030
maxRetries: 3,
31+
sdkKey: 'test-sdk-key',
3132
};
3233
const config = { ...defaultConfig, ...configOverrides };
3334
const batchProcessor = new BatchEventProcessor(eventQueue, batchSize);
@@ -107,30 +108,34 @@ describe('DefaultEventDispatcher', () => {
107108
'http://example.com',
108109
expect.objectContaining({
109110
method: 'POST',
110-
headers: { 'Content-Type': 'application/json' },
111+
headers: { 'Content-Type': 'application/json', 'x-eppo-token': 'test-sdk-key' },
111112
}),
112113
);
113114

114115
let fetchOptions = fetch.mock.calls[0][1];
115116
let payload = JSON.parse(fetchOptions.body);
116-
expect(payload).toEqual([
117-
expect.objectContaining({ payload: { foo: 'event1' } }),
118-
expect.objectContaining({ payload: { foo: 'event2' } }),
119-
]);
117+
expect(payload).toEqual({
118+
eppo_events: [
119+
expect.objectContaining({ payload: { foo: 'event1' } }),
120+
expect.objectContaining({ payload: { foo: 'event2' } }),
121+
],
122+
});
120123

121124
await new Promise((resolve) => setTimeout(resolve, 100));
122125

123126
expect(global.fetch).toHaveBeenCalledWith(
124127
'http://example.com',
125128
expect.objectContaining({
126129
method: 'POST',
127-
headers: { 'Content-Type': 'application/json' },
130+
headers: { 'Content-Type': 'application/json', 'x-eppo-token': 'test-sdk-key' },
128131
}),
129132
);
130133

131134
fetchOptions = fetch.mock.calls[1][1];
132135
payload = JSON.parse(fetchOptions.body);
133-
expect(payload).toEqual([expect.objectContaining({ payload: { foo: 'event3' } })]);
136+
expect(payload).toEqual({
137+
eppo_events: [expect.objectContaining({ payload: { foo: 'event3' } })],
138+
});
134139
});
135140

136141
it('does not schedule delivery if the queue is empty', async () => {

src/events/default-event-dispatcher.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import NoOpEventDispatcher from './no-op-event-dispatcher';
1010
import SdkKeyDecoder from './sdk-key-decoder';
1111

1212
export type EventDispatcherConfig = {
13+
// The Eppo SDK key
14+
sdkKey: string;
1315
// target url to deliver events to
1416
ingestionUrl: string;
1517
// number of milliseconds to wait between each batch delivery
@@ -25,7 +27,10 @@ export type EventDispatcherConfig = {
2527
// TODO: Have more realistic default batch size based on average event payload size once we have
2628
// more concrete data.
2729
export const DEFAULT_EVENT_DISPATCHER_BATCH_SIZE = 100;
28-
export const DEFAULT_EVENT_DISPATCHER_CONFIG: Omit<EventDispatcherConfig, 'ingestionUrl'> = {
30+
export const DEFAULT_EVENT_DISPATCHER_CONFIG: Omit<
31+
EventDispatcherConfig,
32+
'ingestionUrl' | 'sdkKey'
33+
> = {
2934
deliveryIntervalMs: 10_000,
3035
retryIntervalMs: 5_000,
3136
maxRetryDelayMs: 30_000,
@@ -51,11 +56,12 @@ export default class DefaultEventDispatcher implements EventDispatcher {
5156
config: EventDispatcherConfig,
5257
) {
5358
this.ensureConfigFields(config);
54-
this.eventDelivery = new EventDelivery(config.ingestionUrl);
59+
const { sdkKey, ingestionUrl, retryIntervalMs, maxRetryDelayMs, maxRetries = 3 } = config;
60+
this.eventDelivery = new EventDelivery(sdkKey, ingestionUrl);
5561
this.retryManager = new BatchRetryManager(this.eventDelivery, {
56-
retryIntervalMs: config.retryIntervalMs,
57-
maxRetryDelayMs: config.maxRetryDelayMs,
58-
maxRetries: config.maxRetries || 3,
62+
retryIntervalMs,
63+
maxRetryDelayMs,
64+
maxRetries,
5965
});
6066
this.deliveryIntervalMs = config.deliveryIntervalMs;
6167
this.networkStatusListener.onNetworkStatusChange((isOffline) => {
@@ -134,7 +140,7 @@ export function newDefaultEventDispatcher(
134140
networkStatusListener: NetworkStatusListener,
135141
sdkKey: string,
136142
batchSize: number = DEFAULT_EVENT_DISPATCHER_BATCH_SIZE,
137-
config: Omit<EventDispatcherConfig, 'ingestionUrl'> = DEFAULT_EVENT_DISPATCHER_CONFIG,
143+
config: Omit<EventDispatcherConfig, 'ingestionUrl' | 'sdkKey'> = DEFAULT_EVENT_DISPATCHER_CONFIG,
138144
): EventDispatcher {
139145
const sdkKeyDecoder = new SdkKeyDecoder();
140146
const ingestionUrl = sdkKeyDecoder.decodeEventIngestionUrl(sdkKey);
@@ -147,6 +153,6 @@ export function newDefaultEventDispatcher(
147153
return new DefaultEventDispatcher(
148154
new BatchEventProcessor(eventQueue, batchSize),
149155
networkStatusListener,
150-
{ ...config, ingestionUrl },
156+
{ ...config, ingestionUrl, sdkKey },
151157
);
152158
}

src/events/event-delivery.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { logger } from '../application-logger';
33
import { Event } from './event-dispatcher';
44

55
export default class EventDelivery {
6-
constructor(private readonly ingestionUrl: string) {}
6+
constructor(private readonly sdkKey: string, private readonly ingestionUrl: string) {}
77

88
async deliver(batch: Event[]): Promise<boolean> {
99
try {
@@ -12,9 +12,8 @@ export default class EventDelivery {
1212
);
1313
const response = await fetch(this.ingestionUrl, {
1414
method: 'POST',
15-
headers: { 'Content-Type': 'application/json' },
16-
// TODO: Figure out proper request body encoding format for batch, using JSON for now
17-
body: JSON.stringify(batch),
15+
headers: { 'Content-Type': 'application/json', 'x-eppo-token': this.sdkKey },
16+
body: JSON.stringify({ eppo_events: batch }),
1817
});
1918
// TODO: Parse response to check `failed_event_uploads` for any failed event ingestions in the batch
2019
return response.ok;

0 commit comments

Comments
 (0)