Skip to content

Commit 1d05063

Browse files
author
Matt Carroll
committed
Merge branch 'master' into mcarroll/utils-object-entries
2 parents 39fa1eb + fe0b904 commit 1d05063

21 files changed

+222
-57
lines changed

packages/datafile-manager/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77
## [Unreleased]
88
Changes that have landed but are not yet released.
99

10+
## [0.4.0] - June 12, 2019
11+
12+
### Changed
13+
- Changed name of top-level exports in index.node.ts and index.browser.ts from `DatafileManager` to `HttpPollingDatafileManager`, to avoid name conflict with `DatafileManager` interface
14+
1015
## [0.3.0] - May 13, 2019
1116

1217
### New Features

packages/datafile-manager/__test__/httpPollingDatafileManager.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import HTTPPollingDatafileManager from '../src/httpPollingDatafileManager'
17+
import HttpPollingDatafileManager from '../src/httpPollingDatafileManager'
1818
import { Headers, AbortableRequest, Response } from '../src/http'
1919
import { DatafileManagerConfig } from '../src/datafileManager';
2020
import { advanceTimersByTime, getTimerCount } from './testUtils'
@@ -34,7 +34,7 @@ import BackoffController from '../src/backoffController'
3434

3535
// Test implementation:
3636
// - Does not make any real requests: just resolves with queued responses (tests push onto queuedResponses)
37-
class TestDatafileManager extends HTTPPollingDatafileManager {
37+
class TestDatafileManager extends HttpPollingDatafileManager {
3838
queuedResponses: (Response | Error)[] = []
3939

4040
responsePromises: Promise<Response>[] = []

packages/datafile-manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@optimizely/js-sdk-datafile-manager",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "Optimizely Full Stack Datafile Manager",
55
"license": "Apache-2.0",
66
"engines": {

packages/datafile-manager/src/httpPollingDatafileManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function isSuccessStatusCode(statusCode: number): boolean {
3434
return statusCode >= 200 && statusCode < 400
3535
}
3636

37-
export default abstract class HTTPPollingDatafileManager implements DatafileManager {
37+
export default abstract class HttpPollingDatafileManager implements DatafileManager {
3838
// Make an HTTP get request to the given URL with the given headers
3939
// Return an AbortableRequest, which has a promise for a Response.
4040
// If we can't get a response, the promise is rejected.
@@ -208,7 +208,7 @@ export default abstract class HTTPPollingDatafileManager implements DatafileMana
208208
}
209209
}
210210

211-
private onRequestComplete(this: HTTPPollingDatafileManager): void {
211+
private onRequestComplete(this: HttpPollingDatafileManager): void {
212212
if (!this.isStarted) {
213213
return
214214
}

packages/datafile-manager/src/index.browser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
*/
1616

1717
export * from './datafileManager'
18-
export { default as DatafileManager } from './browserDatafileManager'
18+
export { default as HttpPollingDatafileManager } from './browserDatafileManager'
1919
export { default as StaticDatafileManager } from './staticDatafileManager';

packages/datafile-manager/src/index.node.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
*/
1616

1717
export * from './datafileManager'
18-
export { default as DatafileManager } from './nodeDatafileManager'
18+
export { default as HttpPollingDatafileManager } from './nodeDatafileManager'
1919
export { default as StaticDatafileManager } from './staticDatafileManager';

packages/event-processor/CHANGELOG.MD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77
## [Unreleased]
88
Changes that have landed but are not yet released.
99

10+
## [0.2.1] - June 6, 2019
11+
12+
- Wrap the `callback` in `try/catch` when implementing a custom `eventDispatcher`. This ensures invoking the `callback` will always cleanup any pending retry tasks.
13+
1014
## [0.2.0] - March 27, 2019
1115

1216
- Add `PendingEventsDispatcher` to wrap another EventDispatcher with retry support for

packages/event-processor/__tests__/v1EventProcessor.spec.ts

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
/// <reference types="jest" />
1717

1818
import { LogTierV1EventProcessor } from '../src/v1/v1EventProcessor'
19-
import { EventDispatcher, EventV1Request, EventDispatcherCallback } from '../src/eventDispatcher'
19+
import {
20+
EventDispatcher,
21+
EventV1Request,
22+
EventDispatcherCallback,
23+
} from '../src/eventDispatcher'
2024
import { EventProcessor } from '../src/eventProcessor'
2125
import { buildImpressionEventV1, makeBatchedEventV1 } from '../src/v1/buildEventV1'
2226

@@ -118,7 +122,7 @@ describe('LogTierV1EventProcessor', () => {
118122
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void {
119123
dispatchStub(event)
120124
callback({
121-
statusCode: 200
125+
statusCode: 200,
122126
})
123127
},
124128
}
@@ -166,7 +170,7 @@ describe('LogTierV1EventProcessor', () => {
166170
})
167171

168172
localCallback({
169-
statusCode: 200
173+
statusCode: 200,
170174
})
171175
})
172176

@@ -195,7 +199,7 @@ describe('LogTierV1EventProcessor', () => {
195199
})
196200

197201
localCallback({
198-
statusCode: 400
202+
statusCode: 400,
199203
})
200204
})
201205

@@ -204,7 +208,7 @@ describe('LogTierV1EventProcessor', () => {
204208
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void {
205209
dispatchStub(event)
206210
callback({
207-
statusCode: 200
211+
statusCode: 200,
208212
})
209213
},
210214
}
@@ -568,13 +572,55 @@ describe('LogTierV1EventProcessor', () => {
568572
})
569573
})
570574

575+
it('should invoke the callback with result = false event if the dispatcher doesnt provide statusCode', async () => {
576+
const callback = jest.fn()
577+
578+
stubDispatcher = {
579+
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void {
580+
dispatchStub(event)
581+
// @ts-ignore
582+
callback()
583+
},
584+
}
585+
processor = new LogTierV1EventProcessor({
586+
callbacks: [callback],
587+
dispatcher: stubDispatcher,
588+
maxQueueSize: 3,
589+
})
590+
processor.start()
591+
592+
const impressionEvent1 = createImpressionEvent()
593+
const impressionEvent2 = createImpressionEvent()
594+
const impressionEvent3 = createImpressionEvent()
595+
processor.process(impressionEvent1, testProjectConfig)
596+
processor.process(impressionEvent2, testProjectConfig)
597+
processor.process(impressionEvent3, testProjectConfig)
598+
599+
// sleep to let async functions run
600+
await sleep(0)
601+
602+
expect(callback).toHaveBeenCalledTimes(3)
603+
expect(callback).toHaveBeenCalledWith({
604+
event: impressionEvent1,
605+
result: false,
606+
})
607+
expect(callback).toHaveBeenCalledWith({
608+
event: impressionEvent2,
609+
result: false,
610+
})
611+
expect(callback).toHaveBeenCalledWith({
612+
event: impressionEvent3,
613+
result: false,
614+
})
615+
})
616+
571617
it('should return result == false when the dispatcher returns a non 200 response', async () => {
572618
const callback = jest.fn()
573619
const dispatcher: EventDispatcher = {
574620
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void {
575621
dispatchStub(event)
576622
callback({
577-
statusCode: 400
623+
statusCode: 400,
578624
})
579625
},
580626
}

packages/event-processor/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/event-processor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@optimizely/js-sdk-event-processor",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"description": "Optimizely Full Stack Event Processor",
55
"author": "jordangarcia <jordan@optimizely.com>",
66
"homepage": "https://github.com/optimizely/javascript-sdk/tree/master/packages/event-processor",

packages/event-processor/src/eventDispatcher.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { EventV1 } from "./v1/buildEventV1";
1717

1818
export type EventDispatcherResponse = {
1919
statusCode: number
20+
} | {
21+
status: number
2022
}
2123

2224
export type EventDispatcherCallback = (response: EventDispatcherResponse) => void

packages/event-processor/src/eventProcessor.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ export interface EventProcessor extends Managed {
4949
process(event: ProcessableEvents, projectConfig: any): void
5050
}
5151

52+
const MIN_FLUSH_INTERVAL = 100
5253
export abstract class AbstractEventProcessor implements EventProcessor {
53-
static DEFAULT_FLUSH_INTERVAL = 30000
54-
5554
protected transformers: EventTransformer[]
5655
protected interceptors: EventInterceptor[]
5756
protected callbacks: EventCallback[]
@@ -78,7 +77,7 @@ export abstract class AbstractEventProcessor implements EventProcessor {
7877
maxQueueSize = Math.max(1, maxQueueSize)
7978
if (maxQueueSize > 1) {
8079
this.queue = new DefaultEventQueue({
81-
flushInterval,
80+
flushInterval: Math.max(flushInterval, MIN_FLUSH_INTERVAL),
8281
maxQueueSize,
8382
sink: buffer => this.drainQueue(buffer),
8483
})
@@ -170,8 +169,18 @@ export abstract class AbstractEventProcessor implements EventProcessor {
170169
}
171170

172171
function isResponseSuccess(response: EventDispatcherResponse): boolean {
173-
if (!response.statusCode) {
172+
try {
173+
let statusCode: number
174+
if ('statusCode' in response) {
175+
statusCode = response.statusCode
176+
} else if ('status' in response) {
177+
statusCode = response.status
178+
} else {
179+
return false
180+
}
181+
182+
return statusCode >= 200 && statusCode < 300
183+
} catch (e) {
174184
return false
175185
}
176-
return response.statusCode >= 200 && response.statusCode < 300
177186
}

packages/event-processor/src/eventQueue.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class Timer {
3535
private timeoutId?: number
3636

3737
constructor({ timeout, callback }: { timeout: number; callback: () => void }) {
38-
this.timeout = timeout
38+
this.timeout = Math.max(timeout, 0)
3939
this.callback = callback
4040
}
4141

packages/optimizely-sdk/lib/core/project_config/project_config_manager.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ ProjectConfigManager.prototype.__initialize = function(config) {
125125
if (initialDatafile && this.__configObj) {
126126
datafileManagerConfig.datafile = initialDatafile;
127127
}
128-
this.datafileManager = new datafileManager.DatafileManager(datafileManagerConfig);
128+
this.datafileManager = new datafileManager.HttpPollingDatafileManager(datafileManagerConfig);
129129
this.datafileManager.start();
130130
this.__readyPromise = this.datafileManager.onReady().then(
131131
this.__onDatafileManagerReadyFulfill.bind(this),

packages/optimizely-sdk/lib/core/project_config/project_config_manager.tests.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var LOG_MESSAGES = enums.LOG_MESSAGES;
3131
describe('lib/core/project_config/project_config_manager', function() {
3232
var globalStubErrorHandler;
3333
beforeEach(function() {
34-
sinon.stub(datafileManager, 'DatafileManager').returns({
34+
sinon.stub(datafileManager, 'HttpPollingDatafileManager').returns({
3535
start: sinon.stub(),
3636
stop: sinon.stub(),
3737
get: sinon.stub().returns(null),
@@ -50,7 +50,7 @@ describe('lib/core/project_config/project_config_manager', function() {
5050
});
5151

5252
afterEach(function() {
53-
datafileManager.DatafileManager.restore();
53+
datafileManager.HttpPollingDatafileManager.restore();
5454
logging.resetErrorHandler();
5555
logging.resetLogger();
5656
});
@@ -187,8 +187,8 @@ describe('lib/core/project_config/project_config_manager', function() {
187187
updateInterval: 10000,
188188
},
189189
});
190-
sinon.assert.calledOnce(datafileManager.DatafileManager);
191-
sinon.assert.calledWithExactly(datafileManager.DatafileManager, sinon.match({
190+
sinon.assert.calledOnce(datafileManager.HttpPollingDatafileManager);
191+
sinon.assert.calledWithExactly(datafileManager.HttpPollingDatafileManager, sinon.match({
192192
datafile: testData.getTestProjectConfig(),
193193
sdkKey: '12345',
194194
autoUpdate: true,
@@ -199,7 +199,7 @@ describe('lib/core/project_config/project_config_manager', function() {
199199
describe('when constructed with sdkKey and without datafile', function() {
200200
it('updates itself when the datafile manager is ready, fulfills its onReady promise with a successful result, and then emits updates', function() {
201201
var configWithFeatures = testData.getTestProjectConfigWithFeatures();
202-
datafileManager.DatafileManager.returns({
202+
datafileManager.HttpPollingDatafileManager.returns({
203203
start: sinon.stub(),
204204
stop: sinon.stub(),
205205
get: sinon.stub().returns(configWithFeatures),
@@ -231,7 +231,7 @@ describe('lib/core/project_config/project_config_manager', function() {
231231
variations: [{ key: 'variation', id: '99977477477747747' }],
232232
});
233233
nextDatafile.revision = '36';
234-
var fakeDatafileManager = datafileManager.DatafileManager.getCall(0).returnValue;
234+
var fakeDatafileManager = datafileManager.HttpPollingDatafileManager.getCall(0).returnValue;
235235
fakeDatafileManager.get.returns(nextDatafile);
236236
var updateListener = fakeDatafileManager.on.getCall(0).args[1];
237237
updateListener({ datafile: nextDatafile });
@@ -243,7 +243,7 @@ describe('lib/core/project_config/project_config_manager', function() {
243243
});
244244

245245
it('calls onUpdate listeners after becoming ready, and after the datafile manager emits updates', function() {
246-
datafileManager.DatafileManager.returns({
246+
datafileManager.HttpPollingDatafileManager.returns({
247247
start: sinon.stub(),
248248
stop: sinon.stub(),
249249
get: sinon.stub().returns(testData.getTestProjectConfigWithFeatures()),
@@ -258,7 +258,7 @@ describe('lib/core/project_config/project_config_manager', function() {
258258
return manager.onReady().then(function() {
259259
sinon.assert.calledOnce(onUpdateSpy);
260260

261-
var fakeDatafileManager = datafileManager.DatafileManager.getCall(0).returnValue;
261+
var fakeDatafileManager = datafileManager.HttpPollingDatafileManager.getCall(0).returnValue;
262262
var updateListener = fakeDatafileManager.on.getCall(0).args[1];
263263
var newDatafile = testData.getTestProjectConfigWithFeatures();
264264
newDatafile.revision = '36';
@@ -270,7 +270,7 @@ describe('lib/core/project_config/project_config_manager', function() {
270270
});
271271

272272
it('can remove onUpdate listeners using the function returned from onUpdate', function() {
273-
datafileManager.DatafileManager.returns({
273+
datafileManager.HttpPollingDatafileManager.returns({
274274
start: sinon.stub(),
275275
stop: sinon.stub(),
276276
get: sinon.stub().returns(testData.getTestProjectConfigWithFeatures()),
@@ -284,7 +284,7 @@ describe('lib/core/project_config/project_config_manager', function() {
284284
var onUpdateSpy = sinon.spy();
285285
var unsubscribe = manager.onUpdate(onUpdateSpy);
286286

287-
var fakeDatafileManager = datafileManager.DatafileManager.getCall(0).returnValue;
287+
var fakeDatafileManager = datafileManager.HttpPollingDatafileManager.getCall(0).returnValue;
288288
var updateListener = fakeDatafileManager.on.getCall(0).args[1];
289289
var newDatafile = testData.getTestProjectConfigWithFeatures();
290290
newDatafile.revision = '36';
@@ -308,7 +308,7 @@ describe('lib/core/project_config/project_config_manager', function() {
308308
it('fulfills its ready promise with an unsuccessful result when the datafile manager emits an invalid datafile', function() {
309309
var invalidDatafile = testData.getTestProjectConfig();
310310
delete invalidDatafile['projectId'];
311-
datafileManager.DatafileManager.returns({
311+
datafileManager.HttpPollingDatafileManager.returns({
312312
start: sinon.stub(),
313313
stop: sinon.stub(),
314314
get: sinon.stub().returns(invalidDatafile),
@@ -327,7 +327,7 @@ describe('lib/core/project_config/project_config_manager', function() {
327327
});
328328

329329
it('fullfils its ready promise with an unsuccessful result when the datafile manager onReady promise rejects', function() {
330-
datafileManager.DatafileManager.returns({
330+
datafileManager.HttpPollingDatafileManager.returns({
331331
start: sinon.stub(),
332332
stop: sinon.stub(),
333333
get: sinon.stub().returns(null),
@@ -350,13 +350,13 @@ describe('lib/core/project_config/project_config_manager', function() {
350350
sdkKey: '12345',
351351
});
352352
manager.stop();
353-
sinon.assert.calledOnce(datafileManager.DatafileManager.getCall(0).returnValue.stop);
353+
sinon.assert.calledOnce(datafileManager.HttpPollingDatafileManager.getCall(0).returnValue.stop);
354354
});
355355
});
356356

357357
describe('when constructed with sdkKey and with a valid datafile object', function() {
358358
it('fulfills its onReady promise with a successful result, and does not call onUpdate listeners after becoming ready', function() {
359-
datafileManager.DatafileManager.returns({
359+
datafileManager.HttpPollingDatafileManager.returns({
360360
start: sinon.stub(),
361361
stop: sinon.stub(),
362362
get: sinon.stub().returns(testData.getTestProjectConfigWithFeatures()),
@@ -383,7 +383,7 @@ describe('lib/core/project_config/project_config_manager', function() {
383383

384384
describe('when constructed with sdkKey and with a valid datafile string', function() {
385385
it('fulfills its onReady promise with a successful result, and does not call onUpdate listeners after becoming ready', function() {
386-
datafileManager.DatafileManager.returns({
386+
datafileManager.HttpPollingDatafileManager.returns({
387387
start: sinon.stub(),
388388
stop: sinon.stub(),
389389
get: sinon.stub().returns(testData.getTestProjectConfigWithFeatures()),

0 commit comments

Comments
 (0)