Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/npm_and_yarn/packages/optimizel…
Browse files Browse the repository at this point in the history
…y-sdk/handlebars-4.1.2
  • Loading branch information
mikeproeng37 authored Jul 11, 2019
2 parents f7664d3 + a7060ea commit 675b540
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 6 deletions.
5 changes: 5 additions & 0 deletions packages/optimizely-sdk/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
Changes that have landed but are not yet released.

### New Features
- Updated the `close` method to return a `Promise` representing the process of closing the instance. When `close` is called, any events waiting to be sent as part of a batched event request will be immediately batched and sent to the event dispatcher.
- If any such requests were sent to the event dispatcher, `close` returns a `Promise` that fulfills after the event dispatcher calls the response callback for each request. Otherwise, `close` returns an immediately-fulfilled `Promise`.
- The `Promise` returned from `close` is fulfilled with a result object containing `success` (boolean) and `reason` (string, only when success is `false`) properties. In the result object, `success` is `true` if all events in the queue at the time close was called were combined into requests, sent to the event dispatcher, and the event dispatcher called the callbacks for each request. `success` is false if an unexpected error was encountered during the close process.

## [3.2.1] - July 1st, 2019

### Changed
Expand Down
2 changes: 1 addition & 1 deletion packages/optimizely-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![license](https://img.shields.io/github/license/optimizely/javascript-sdk.svg)](https://choosealicense.com/licenses/apache-2.0/)


Optimizely X Full Stack is A/B testing and feature management for product development teams. Experiment in any application. Make every feature on your roadmap an opportunity to learn. Learn more at the [landing page](https://www.optimizely.com/products/full-stack/), or see the [documentation](https://developers.optimizely.com/x/solutions/sdks/reference/index.html?language=node).
Optimizely X Full Stack is A/B testing and feature management for product development teams. Experiment in any application. Make every feature on your roadmap an opportunity to learn. Learn more at the [landing page](https://www.optimizely.com/products/full-stack/), or see the [documentation](https://docs.developers.optimizely.com/full-stack/docs).

This directory contains the source code for the JavaScript SDK, which is usable in Node.js, browsers, and beyond.

Expand Down
54 changes: 49 additions & 5 deletions packages/optimizely-sdk/lib/optimizely/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -850,11 +850,38 @@ Optimizely.prototype.getFeatureVariableString = function(featureKey, variableKey
};

/**
* Cleanup method for killing an running timers and flushing eventQueue
* Stop background processes belonging to this instance, including:
*
* - Active datafile requests
* - Pending datafile requests
* - Pending event queue flushes
*
* In-flight datafile requests will be aborted. Any events waiting to be sent
* as part of a batched event request will be immediately batched and sent to
* the event dispatcher.
*
* If any such requests were sent to the event dispatcher, returns a Promise
* that fulfills after the event dispatcher calls the response callback for each
* request. Otherwise, returns an immediately-fulfilled Promise.
*
* Returned Promises are fulfilled with result objects containing these
* properties:
* - success (boolean): true if all events in the queue at the time close was
* called were combined into requests, sent to the
* event dispatcher, and the event dispatcher called the
* callbacks for each request. false if an unexpected
* error was encountered during the close process.
* - reason (string=): If success is false, this is a string property with
* an explanatory message.
*
* NOTE: After close is called, this instance is no longer usable - any events
* generated will no longer be sent to the event dispatcher.
*
* @return {Promise}
*/
Optimizely.prototype.close = function() {
try {
this.eventProcessor.stop();
var eventProcessorStoppedPromise = this.eventProcessor.stop();
if (this.__disposeOnUpdate) {
this.__disposeOnUpdate();
this.__disposeOnUpdate = null;
Expand All @@ -868,9 +895,26 @@ Optimizely.prototype.close = function() {
readyTimeoutRecord.onClose();
}.bind(this));
this.__readyTimeouts = {};
} catch (e) {
this.logger.log(LOG_LEVEL.ERROR, e.message);
this.errorHandler.handleError(e);
return eventProcessorStoppedPromise.then(
function() {
return {
success: true,
};
},
function(err) {
return {
success: false,
reason: String(err),
};
}
);
} catch (err) {
this.logger.log(LOG_LEVEL.ERROR, err.message);
this.errorHandler.handleError(err);
return Promise.resolve({
success: false,
reason: String(err),
});
}
};

Expand Down
83 changes: 83 additions & 0 deletions packages/optimizely-sdk/lib/optimizely/index.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4768,6 +4768,89 @@ describe('lib/optimizely', function() {
assert.deepEqual(eventDispatcherCall[0], expectedObj);
});
});

describe('close method', function() {
var eventProcessorStopPromise;
var optlyInstance;
var mockEventProcessor;
beforeEach(function() {
mockEventProcessor = {
process: sinon.stub(),
start: sinon.stub(),
stop: sinon.stub(),
};
sinon.stub(eventProcessor, 'LogTierV1EventProcessor').returns(mockEventProcessor);
});

afterEach(function() {
eventProcessor.LogTierV1EventProcessor.restore();
});

describe('when the event processor stop method returns a promise that fulfills', function() {
beforeEach(function() {
eventProcessorStopPromise = Promise.resolve();
mockEventProcessor.stop.returns(eventProcessorStopPromise);
optlyInstance = new Optimizely({
clientEngine: 'node-sdk',
datafile: testData.getTestProjectConfig(),
eventBuilder: eventBuilder,
errorHandler: errorHandler,
eventDispatcher: eventDispatcher,
jsonSchemaValidator: jsonSchemaValidator,
logger: createdLogger,
isValidInstance: true,
eventBatchSize: 3,
eventFlushInterval: 100,
});
});

afterEach(function() {
return eventProcessorStopPromise.catch(function() {
// Handle rejected promise - don't want test to fail
});
});

it('returns a promise that fulfills with a successful result object', function() {
return optlyInstance.close().then(function(result) {
assert.deepEqual(result, { success: true });
});
});
});

describe('when the event processor stop method returns a promise that rejects', function() {
beforeEach(function() {
eventProcessorStopPromise = Promise.reject(new Error('Failed to stop'));
mockEventProcessor.stop.returns(eventProcessorStopPromise);
optlyInstance = new Optimizely({
clientEngine: 'node-sdk',
datafile: testData.getTestProjectConfig(),
eventBuilder: eventBuilder,
errorHandler: errorHandler,
eventDispatcher: eventDispatcher,
jsonSchemaValidator: jsonSchemaValidator,
logger: createdLogger,
isValidInstance: true,
eventBatchSize: 3,
eventFlushInterval: 100,
});
});

afterEach(function() {
return eventProcessorStopPromise.catch(function() {
// Handle rejected promise - don't want test to fail
});
});

it('returns a promise that fulfills with an unsuccessful result object', function() {
return optlyInstance.close().then(function(result) {
assert.deepEqual(result, {
success: false,
reason: 'Error: Failed to stop',
});
});
});
});
});
});

describe('event processor defaults', function() {
Expand Down

0 comments on commit 675b540

Please sign in to comment.