Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

twilio-sync

Package Overview
Dependencies
Maintainers
2
Versions
608
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

twilio-sync - npm Package Compare versions

Comparing version 0.3.1-alpha.2 to 0.3.1

32

lib/client.js

@@ -164,6 +164,8 @@ 'use strict';

var productId = options.productId || SYNC_PRODUCT_ID;
options.productId = options.productId || SYNC_PRODUCT_ID;
var productId = options.productId;
options.twilsockClient = options.twilsockClient || new _twilsock2.default(token, options);
options.transport = options.transport || new _twilioTransport2.default(options.twilsockClient);
options.notificationsClient = options.notificationsClient || new _twilioNotifications2.default(productId, token, options);
options.notificationsClient = options.notificationsClient || new _twilioNotifications2.default(token, options);

@@ -267,2 +269,7 @@ var transport = options.transport;

}
}, {
key: '_removeFromCache',
value: function _removeFromCache(sid) {
this._entities.remove(sid);
}

@@ -287,3 +294,3 @@ /**

return this._getCached(id, 'doc') || this._getDocument(id).then(function (body) {
return this._getCached(id, 'document') || this._getDocument(id).then(function (body) {
if (body) {

@@ -296,3 +303,5 @@ return body;

}).then(function (body) {
return new _syncdocument2.default(_this2._dependencies, body);
return new _syncdocument2.default(_this2._dependencies, body, function (sid) {
return _this2._removeFromCache(sid);
});
}).then(function (entity) {

@@ -329,3 +338,5 @@ return _this2._entities.store(entity);

}).then(function (body) {
return new _syncmap2.default(_this3._dependencies, body);
return new _syncmap2.default(_this3._dependencies, body, function (sid) {
return _this3._removeFromCache(sid);
});
}).then(function (entity) {

@@ -362,3 +373,5 @@ return _this3._entities.store(entity);

}).then(function (body) {
return new _synclist2.default(_this4._dependencies, body);
return new _synclist2.default(_this4._dependencies, body, function (sid) {
return _this4._removeFromCache(sid);
});
}).then(function (entity) {

@@ -379,4 +392,7 @@ return _this4._entities.store(entity);

value: function shutdown() {
this._subscriptions.shutdown();
this._twilsock.disconnect().then(function () {});
var _this5 = this;
return this._subscriptions.shutdown().then(function () {
return _this5._twilsock.disconnect();
}).then(function () {});
}

@@ -383,0 +399,0 @@

@@ -22,3 +22,3 @@ 'use strict';

var CDS_URI = 'https://cds.twilio.com';
var SUBSCRIPTIONS_PATH = '/v4/Subscriptions';
var SUBSCRIPTIONS_PATH = '/v3/Subscriptions';
var MAPS_PATH = '/v3/Maps';

@@ -25,0 +25,0 @@ var LISTS_PATH = '/v3/Lists';

@@ -59,2 +59,13 @@ 'use strict';

}, {
key: 'remove',
value: function remove(sid) {
var cached = this._entities.get(sid);
if (cached) {
this._entities.delete(sid);
if (cached.uniqueName) {
this._names.delete(cached.type + '::' + cached.uniqueName);
}
}
}
}, {
key: '_getResolved',

@@ -61,0 +72,0 @@ value: function _getResolved(id, type) {

@@ -72,3 +72,3 @@ 'use strict';

value: function _unsubscribe() {
this._deps.router.unsubscribe(this.sid);
this._deps.router.unsubscribe(this.sid, this);
return this;

@@ -75,0 +75,0 @@ }

@@ -7,6 +7,2 @@ 'use strict';

var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _defineProperties = require('babel-runtime/core-js/object/define-properties');

@@ -28,2 +24,4 @@

var _utils = require('./utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -34,3 +32,2 @@

var COREDATA_MAP_NOTIFICATION_TYPE = 'com.twilio.rtd.cds.map';
var SYNC_NOTIFICATION_TYPE = 'twilio.sync.event';

@@ -57,3 +54,2 @@ /**

this._notifications.subscribe(COREDATA_MAP_NOTIFICATION_TYPE);
this._notifications.subscribe(SYNC_NOTIFICATION_TYPE);

@@ -78,6 +74,25 @@ this._notifications.on('message', this.onMessage.bind(this));

value: function onMessage(type, message) {
// As it happens, all message types are intended for the Subscriptions manager.
//
_logger2.default.trace('Notification type:', type, 'content:', message);
this._subscriptions.acceptMessage(message);
var id = void 0;
switch (type) {
case COREDATA_DOCUMENT_NOTIFICATION_TYPE:
id = message.event.document_sid;
break;
case COREDATA_LIST_NOTIFICATION_TYPE:
id = message.event.list_sid;
break;
case COREDATA_MAP_NOTIFICATION_TYPE:
id = message.event.map_sid;
break;
default:
_logger2.default.warn('Unknown message type:', type, 'ignoring');
}
if (id) {
message.event.type = message.event_type; // Patch message
this._subscriptions.getSubscribers(id).forEach(function (entity) {
entity._update((0, _utils.deepClone)(message.event));
});
}
}

@@ -92,4 +107,9 @@

value: function subscribe(sid, entity) {
this._subscriptions.add(sid, entity);
return _promise2.default.resolve(entity);
return this._subscriptions.add(sid, entity).then(function (isNewSubscription) {
if (isNewSubscription) {
entity._softSync();
}
}).then(function () {
return entity;
});
}

@@ -103,4 +123,6 @@

key: 'unsubscribe',
value: function unsubscribe(sid) {
return this._subscriptions.remove(sid);
value: function unsubscribe(sid, entity) {
return this._subscriptions.remove(sid, entity).then(function () {
return entity;
});
}

@@ -116,3 +138,5 @@

value: function onConnected() {
this._subscriptions.poke();
this._subscriptions.forEach(function (id, endpoint) {
endpoint._softSync();
});
}

@@ -119,0 +143,0 @@ }]);

@@ -7,5 +7,5 @@ 'use strict';

var _typeof2 = require('babel-runtime/helpers/typeof');
var _set = require('babel-runtime/core-js/set');
var _typeof3 = _interopRequireDefault(_typeof2);
var _set2 = _interopRequireDefault(_set);

@@ -16,14 +16,10 @@ var _promise = require('babel-runtime/core-js/promise');

var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _map = require('babel-runtime/core-js/map');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _map2 = _interopRequireDefault(_map);
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _defineProperties = require('babel-runtime/core-js/object/define-properties');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _defineProperties2 = _interopRequireDefault(_defineProperties);
var _map = require('babel-runtime/core-js/map');
var _map2 = _interopRequireDefault(_map);
var _extends2 = require('babel-runtime/helpers/extends');

@@ -33,2 +29,6 @@

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');

@@ -38,9 +38,9 @@

var _defineProperties = require('babel-runtime/core-js/object/define-properties');
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _defineProperties2 = _interopRequireDefault(_defineProperties);
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _getIterator3 = _interopRequireDefault(_getIterator2);

@@ -55,54 +55,46 @@ var _backoff = require('backoff');

var _utils = require('./utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* A data container used by the Subscriptions class to track subscribed entities' local
* representations and their state.
*/
var SubscribedEntity = function SubscribedEntity(entity) {
(0, _classCallCheck3.default)(this, SubscribedEntity);
function substract(p1, p2) {
var result = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
(0, _defineProperties2.default)(this, {
sid: { get: function get() {
return entity.sid;
} },
type: { get: function get() {
return entity.type;
} },
localObject: { value: entity },
try {
for (var _iterator = (0, _getIterator3.default)(p1), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _step$value = (0, _slicedToArray3.default)(_step.value, 2),
key = _step$value[0],
value = _step$value[1];
correlationId: { value: null, writable: true },
pendingPokeTimer: { value: null, writable: true },
lastPokeYieldEventId: { value: null, writable: true },
if (!p2.has(key)) {
result.push({ sid: key, type: value.type });
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
lastEventId: { get: function get() {
return entity.lastEventId;
} },
return result;
}
promise: { value: null, writable: true },
resolve: { value: null, writable: true },
reject: { value: null, writable: true }
});
};
/**
* @class Subscriptions
* @classdesc A manager which, in batches of varying size, continuously persists the
* subscription intent of the caller to the Sync backend until it achieves a
* converged state.
* @classdesc Subscriptions container for CDS objects
*/
/* eslint-disable key-spacing */
var Subscriptions = function () {
/**
* @constructor
* Prepares a new Subscriptions manager object with zero subscribed or persisted subscriptions.
*
* @param {object} config may include a key 'backoffConfig', wherein any of the parameters
* of Backoff.exponential (from npm 'backoff') are valid and will override the defaults.
*
* @param {Network} must be a viable running Sync Network object, useful for routing requests.
*/

@@ -123,2 +115,3 @@ function Subscriptions(config, network) {

}
(0, _defineProperties2.default)(this, {

@@ -129,27 +122,26 @@ _config: { value: config },

// This is always the full set of subscribables (SubscribedEntity instances) intended by
// the client. At any point, whatever the state of these subscriptions on the server, this
// is the intent of the user to which the SDK must converge.
_types: { value: new _map2.default() },
_subscriptions: { value: new _map2.default() },
// This includes the set of subscribables (SubscribedEntity instances) for whom a request
// has been dispatched (whether or not this particular request ultimately succeeds) to
// establish a live subscription. Entities are removed when the corresponding "cancel"
// request is dispatched.
_persisted: { value: new _map2.default() }
});
// This block is triggered by #_persist. Every request is executed in a series of (ideally 1)
// backoff 'ready' event, at which point a new subscription set is calculated.
//
this._backoff.on('ready', function () {
var _getSubscriptionUpdat = _this._getSubscriptionUpdateBatch(),
action = _getSubscriptionUpdat.action,
subscriptionRequests = _getSubscriptionUpdat.subscriptions;
var _getAction2 = _this._getAction(),
action = _getAction2.action,
list = _getAction2.list;
if (action) {
_this._applyNewSubscriptionUpdateBatch(action, subscriptionRequests);
_this._request(action, list.map(function (x) {
return { object_sid: x.sid, object_type: x.type };
})) // eslint-disable-line camelcase
.then(function () {
_this._backoff.reset();
_this._backoff.backoff();
}).catch(function (e) {
_logger2.default.error('Error while persisting subscriptions, retrying', action, e);
_this._backoff.backoff(e);
});
} else {
_this._backoff.reset();
_logger2.default.info('All subscriptions scheduled or resolved.');
_logger2.default.info('Subscription list persisted');
}

@@ -160,45 +152,16 @@ });

(0, _createClass3.default)(Subscriptions, [{
key: '_getSubscriptionUpdateBatch',
value: function _getSubscriptionUpdateBatch() {
function substract(these, those) {
var result = [];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
key: '_getAction',
value: function _getAction() {
var _this2 = this;
try {
for (var _iterator = (0, _getIterator3.default)(these), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _step$value = (0, _slicedToArray3.default)(_step.value, 2),
thisKey = _step$value[0],
thisValue = _step$value[1];
var otherValue = those.get(thisKey);
if (!otherValue || otherValue.correlationId !== thisValue.correlationId) result.push(thisValue);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return result;
}
var listToAdd = substract(this._subscriptions, this._persisted);
if (listToAdd.length > 0) {
return { action: 'establish', subscriptions: listToAdd };
return { action: 'establish', list: listToAdd };
}
var listToRemove = substract(this._persisted, this._subscriptions);
var listToRemove = substract(this._persisted, this._subscriptions).map(function (x) {
return { sid: x.sid, type: _this2._types.get(x.sid) };
});
if (listToRemove.length > 0) {
return { action: 'cancel', subscriptions: listToRemove };
return { action: 'cancel', list: listToRemove };
}

@@ -215,110 +178,3 @@

}
}, {
key: '_applyNewSubscriptionUpdateBatch',
value: function _applyNewSubscriptionUpdateBatch(action, requests) {
var _this2 = this;
// Keeping in mind that events may begin flowing _before_ we receive the response
// below, set ourselves up to be able to correlate those events to the current
// request properly.
//
var correlationId = new Date().getTime();
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)(requests), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var subscribed = _step2.value;
this._recordActionAttemptOn(subscribed, action, correlationId);
} // Send this batch to the service…
//
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
this._request(action, correlationId, requests.map(function (object) {
return {
object_sid: object.sid, // eslint-disable-line camelcase
object_type: object.type, // eslint-disable-line camelcase
last_event_id: action === 'establish' ? object.lastPokeYieldEventId || object.lastEventId : // eslint-disable-line camelcase
undefined // eslint-disable-line no-undefined
};
})).then(function (response) {
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = (0, _getIterator3.default)(requests), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var subscribed = _step3.value;
if (action === 'establish') _this2._beginReplayTimeout(response.body.estimated_delivery_in_ms, subscribed, action);
subscribed.resolve();
}
// Start looking for the next batch…
//
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
_this2._backoff.reset();
_this2._backoff.backoff();
}).catch(function (e) {
_logger2.default.info('failed an attempt to ' + action + ' subscriptions; retrying', e);
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = (0, _getIterator3.default)(requests), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var attemptedSubscription = _step4.value;
_this2._recordActionFailureOn(attemptedSubscription, action);
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
_this2._backoff.backoff(e);
});
}
/**

@@ -330,76 +186,34 @@ * @private

key: '_request',
value: function _request(action, correlationId, requests) {
value: function _request(action, requests) {
var _this3 = this;
_logger2.default.debug('Modifying server subscriptions: ', action, requests);
/* eslint-disable camelcase */
var requestBody = {
event_protocol_version: 3, // eslint-disable-line camelcase
action: action,
correlation_id: correlationId,
requests: requests
};
/* eslint-enable camelcase */
return this._network.post(this._config.subscriptionsUri, requestBody);
return this._network.post(this._config.subscriptionsUri, requestBody).then(function (response) {
response.body.results.forEach(function (persisted) {
if (!persisted.subscription) {
_this3._persisted.delete(persisted.object_sid);
_this3._types.delete(persisted.object_sid);
} else {
_this3._persisted.set(persisted.object_sid, persisted.subscription);
var subscription = _this3._subscriptions.get(persisted.object_sid);
if (subscription) {
subscription.resolve(true);
}
}
});
});
}
}, {
key: '_beginReplayTimeout',
value: function _beginReplayTimeout(timeout, subscription, action) {
var _this3 = this;
var isNumeric = !isNaN(parseFloat(timeout)) && isFinite(timeout);
var isValidTimeout = isNumeric && timeout > 0;
if (isValidTimeout) {
subscription.pendingPokeTimer = setTimeout(function () {
_logger2.default.debug('Attempt to ' + action + ' ' + subscription.sid + ' timed out without confirmation; trying again.');
_this3._persisted.delete(subscription.sid);
_this3._persist();
}, timeout);
}
}
}, {
key: '_recordActionAttemptOn',
value: function _recordActionAttemptOn(attemptedSubscription, action, correlationId) {
if (action === 'establish') {
this._persisted.set(attemptedSubscription.sid, attemptedSubscription);
attemptedSubscription.correlationId = correlationId;
} else if (action === 'cancel') {
this._persisted.delete(attemptedSubscription.sid);
}
}
}, {
key: '_recordActionFailureOn',
value: function _recordActionFailureOn(attemptedSubscription, action) {
if (action === 'establish') {
this._persisted.delete(attemptedSubscription.sid);
} else {
// action == 'cancel'
var newSubscriptionMeanwhile = this._subscriptions.get(attemptedSubscription.sid);
if (!newSubscriptionMeanwhile || newSubscriptionMeanwhile.correlationId !== attemptedSubscription.correlationId) {
this._persisted.set(attemptedSubscription.sid, attemptedSubscription);
} else {
/* force resubscription by leaving this sid out of the _persisted set */
}
}
}
/**
* Establishes intent to be subscribed to this entity. That subscription will be effected
* asynchronously, with the returned promise indicating its eventual success, failure or
* cancellation due to an intervening call to #remove.
*
* The Subscriptions class does not attempt any reference counting or support for multiple
* local representations of the same Sync entity. If the local application attempts any such
* games, it must provide a single proxy to the actual entity (i.e. a splitter) to this
* method. The first provided proxy wins; all subsequent entities, unless preceded by a call
* to #remove, are ignored and will not receive events.
*
* @param {string} sid should be a well-formed SID, uniquely identifying a single instance of a Sync entity.
* @param {object} entity should represent the (singular) local representation of this entity.
* Incoming events and modifications to the entity will be directed at the _update() function
* of this provided reference.
*
* @return Promise<void> which is resolved if and when a subscription is both a) effected and
* b) completes any necessary event replay. Subscriptions are attempted infinitely; a
* rejection is therefore the result of cancellation in some form.
* Add subscription
* @param {string} uri URI to the server object
* @param {object} endpoint Endpoint object
* @return Promise<boolean> true if subscription haven't been there before
*/

@@ -412,41 +226,35 @@

_logger2.default.debug('Establishing intent to subscribe to ' + sid);
var subscribed = this._subscriptions.has(sid);
var persisted = this._persisted.has(sid);
if (subscribed) {
var subscription = this._subscriptions.get(sid);
return subscription.promise;
} else {
var _ret = function () {
var newSubscription = new SubscribedEntity(entity);
if (subscribed && persisted) {
var _subscription = this._subscriptions.get(sid);
_subscription.subscribers.add(entity);
return _promise2.default.resolve(false);
} else if (this._subscribed && !persisted) {
var _subscription2 = this._subscriptions.get(sid);
return _subscription2.promise;
}
_this4._subscriptions.set(sid, newSubscription);
var promiseToSubscribe = new _promise2.default(function (resolve, reject) {
newSubscription.resolve = resolve;
newSubscription.reject = reject;
});
newSubscription.promise = promiseToSubscribe;
_this4._persist();
var subscription = { type: entity.type,
subscribers: new _set2.default([entity]),
promise: null,
resolve: null,
reject: null
};
return {
v: promiseToSubscribe
};
}();
if ((typeof _ret === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret)) === "object") return _ret.v;
}
this._subscriptions.set(sid, subscription);
var promiseToSubscribe = new _promise2.default(function (resolve, reject) {
subscription.resolve = resolve;
subscription.reject = reject;
_this4._persist();
});
subscription.promise = promiseToSubscribe;
return promiseToSubscribe;
}
/**
* Establishes the caller's intent to no longer be subscribed to this entity. Following this
* call, no further events shall be routed to the local representation of the entity, even
* though a server-side subscription may take more time to actually terminate.
*
* @param {string} sid should be any well-formed SID, uniquely identifying a Sync entity.
* This parameter only has meaningful effect if that entity is also subscribed at the
* time of call, but providing a SID with no active subscription will simply yield
* a resolved promise.
*
* @return Promise<void> which is resolved if and when the unsubscription is effected on
* the server. Rejected if it is overridden by a subsequent re-subscription.
* Remove subscription for the entity
* @param {string} entityUri URI
* @param {object} endpoint Endpoint object
*/

@@ -456,150 +264,88 @@

key: 'remove',
value: function remove(sid) {
var _this5 = this;
value: function remove(id, entity) {
if (!this._subscriptions.has(id)) {
return _promise2.default.resolve(true);
}
_logger2.default.debug('Establishing intent to unsubscribe from ' + sid);
var subscribed = this._subscriptions.has(sid);
var persisted = this._persisted.has(sid);
var subscription = this._subscriptions.get(id);
if (!subscription.subscribers.has(entity)) {
return _promise2.default.resolve(false);
}
if (!subscribed) {
return persisted ? this._persisted.get(sid).promise // unsubscribe hadn't been scheduled yet.
: _promise2.default.resolve(); // already unsubscribed.
} else {
var subscriptionPersisted = this._persisted.get(sid);
var subscriptionIntent = this._subscriptions.get(sid);
if (!persisted || subscriptionIntent.correlationId !== subscriptionPersisted.correlationId) {
var intentToSubscribe = this._subscriptions.get(sid);
this._subscriptions.delete(sid);
intentToSubscribe.reject('Subscription canceled.');
return _promise2.default.resolve();
} else {
var _ret2 = function () {
var subscriptionToCancel = _this5._persisted.get(sid);
var promiseToUnsubscribe = new _promise2.default(function (resolve, reject) {
subscriptionToCancel.resolve = resolve;
subscriptionToCancel.reject = reject;
});
subscriptionToCancel.promise = promiseToUnsubscribe;
subscription.subscribers.delete(entity);
if (subscription.subscribers.size > 0) {
return _promise2.default.resolve(false);
}
_this5._subscriptions.delete(sid);
return {
v: subscriptionToCancel.promise
};
}();
// It's a hack: since server responce doesn't contain a type, but we need it
// we should always keep it locally
this._types.set(id, subscription.type);
if ((typeof _ret2 === 'undefined' ? 'undefined' : (0, _typeof3.default)(_ret2)) === "object") return _ret2.v;
}
}
this._subscriptions.delete(id);
this._persist();
return _promise2.default.resolve(true);
}
/**
* The point of ingestion for remote incoming messages (e.g. new data was written to a map
* to which we are subscribed).
*
* @param {object} message is the full, unaltered body of the incoming notification.
*
* @return undefined
* Query subscribers for given URI
* @return {set}
*/
}, {
key: 'acceptMessage',
value: function acceptMessage(message) {
_logger2.default.trace('Subscriptions received', message);
key: 'getSubscribers',
value: function getSubscribers(id) {
var subscription = this._subscriptions.get(id);
return subscription && subscription.subscribers ? subscription.subscribers : new _set2.default();
}
switch (message.event_type) {
case 'subscription_established':
this._applyControlMessage(message.event, message.correlation_id); // eslint-disable-line camelCase
break;
/**
* Iterates through all subscriptions
* @param {function} hanlder function to call for each subscription
*/
case 'subscription_canceled':
// TODO
break;
case (message.event_type.match(/^(?:map|list|document)_/) || {}).input:
{
var typedSid = function typedSid() {
if (message.event_type.match(/^map_/)) return message.event.map_sid;else if (message.event_type.match(/^list_/)) return message.event.list_sid;else if (message.event_type.match(/^document_/)) return message.event.document_sid;else return undefined; // eslint-disable-line no-undefined
};
this._applyEventToSubscribedEntity(typedSid(), message);
}
break;
default:
_logger2.default.debug('Dropping unknown message type ' + message.event_type);
break;
}
}
}, {
key: '_applyControlMessage',
value: function _applyControlMessage(message, correlationId) {
var subscriptionIntent = this._subscriptions.get(message.object_sid);
if (subscriptionIntent && correlationId === subscriptionIntent.correlationId) {
if (message.replay_status === 'interrupted') {
_logger2.default.debug('Event Replay for subscription to ' + subscriptionIntent.sid + ' interrupted; continuing eagerly.');
clearTimeout(subscriptionIntent.pendingPokeTimer);
subscriptionIntent.pendingPokeTimer = null;
subscriptionIntent.correlationId = null;
this._persisted.delete(message.object_sid);
this._persist();
} else if (message.replay_status === 'completed') {
_logger2.default.debug('Event Replay for subscription to ' + subscriptionIntent.sid + ' completed. Subscription is ready.');
clearTimeout(subscriptionIntent.pendingPokeTimer);
subscriptionIntent.pendingPokeTimer = null;
}
} else {
_logger2.default.debug('Late message (correlation_id: ' + message.correlation_id + ') dropped.');
}
key: 'forEach',
value: function forEach(handler) {
this._subscriptions.forEach(function (subscription, id) {
subscription.subscribers.forEach(function (subscriber) {
return handler(id, subscriber);
});
});
}
}, {
key: '_applyEventToSubscribedEntity',
value: function _applyEventToSubscribedEntity(sid, message) {
var subscriptionIntent = sid ? this._subscriptions.get(sid) : undefined; // eslint-disable-line no-undefined
if (sid && subscriptionIntent) {
message.event.type = message.event_type;
subscriptionIntent.localObject._update((0, _utils.deepClone)(message.event));
if (message.correlation_id && subscriptionIntent.correlationId === message.correlation_id) subscriptionIntent.lastPokeYieldEventId = message.event.id;
} else {
_logger2.default.debug('Message dropped for SID \'' + sid + '\', for which there is no subscription.');
}
}
/**
* Prompts a playback of any missed changes made to any subscribed object. This method
* should be invoked whenever the connectivity layer has experienced cross-cutting
* delivery failures that would affect the entire local sync set. Any tangible result
* of this operation will result in calls to the _update() function of subscribed
* Sync entities.
* Currently just resets retries
* Should remove all subscriptions
*/
}, {
key: 'poke',
value: function poke() {
_logger2.default.info('Triggering event replay for all subscriptions.');
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
key: 'shutdown',
value: function shutdown() {
this._backoff.reset();
this._subscriptions.clear();
var listToRemove = [];
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator5 = (0, _getIterator3.default)(this._persisted), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var _step5$value = (0, _slicedToArray3.default)(_step5.value, 2),
_ = _step5$value[0],
it = _step5$value[1];
for (var _iterator2 = (0, _getIterator3.default)(this._persisted), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _step2$value = (0, _slicedToArray3.default)(_step2.value, 2),
key = _step2$value[0],
value = _step2$value[1];
// eslint-disable-line no-unused-vars
clearTimeout(it.pendingPokeTimer);
it.pendingPokeTimer = null;
listToRemove.push({ object_sid: key, type: value.type }); // eslint-disable-line camelcase
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5.return) {
_iterator5.return();
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
if (_didIteratorError2) {
throw _iteratorError2;
}

@@ -609,17 +355,7 @@ }

this._persisted.clear();
this._persist();
if (listToRemove.length > 0) {
return this._request('cancel', listToRemove).catch(function () {});
}
return _promise2.default.resolve();
}
/**
* Stops all communication, clears any subscription intent, and returns.
*/
}, {
key: 'shutdown',
value: function shutdown() {
this._backoff.reset();
this._subscriptions.clear();
}
}]);

@@ -626,0 +362,0 @@ return Subscriptions;

@@ -74,3 +74,3 @@ 'use strict';

*/
function SyncDocument(params, descriptor) {
function SyncDocument(params, descriptor, onRemoveDocument) {
(0, _classCallCheck3.default)(this, SyncDocument);

@@ -88,2 +88,3 @@

_pendingListeners: { value: {} },
_onRemoveDocument: { value: onRemoveDocument },

@@ -376,2 +377,3 @@ _descriptor: { value: descriptor },

this._onRemoveDocument(this.sid);
return this._network.delete(this.uri).then(function () {

@@ -386,7 +388,2 @@ _this8.emit('removed', true);

}
}, {
key: 'lastEventId',
get: function get() {
return this._lastEventId;
}
}]);

@@ -393,0 +390,0 @@ return SyncDocument;

@@ -92,3 +92,3 @@ 'use strict';

*/
function SyncList(deps, descriptor) {
function SyncList(deps, descriptor, onRemoveList) {
(0, _classCallCheck3.default)(this, SyncList);

@@ -106,2 +106,3 @@

_cache: { value: new _cache2.default() },
_onRemoveList: { value: onRemoveList },

@@ -436,2 +437,3 @@ _links: { get: function get() {

this._onRemoveList(this.sid);
return this._deps.network.delete(this.uri).then(function () {

@@ -570,7 +572,2 @@ _this12.emit('collectionRemoved', true);

}
}, {
key: 'lastEventId',
get: function get() {
return this._lastEventId;
}
}]);

@@ -577,0 +574,0 @@ return SyncList;

@@ -90,3 +90,3 @@ 'use strict';

*/
function SyncMap(deps, descriptor) {
function SyncMap(deps, descriptor, onRemoveMap) {
(0, _classCallCheck3.default)(this, SyncMap);

@@ -106,2 +106,3 @@

_updateQueue: { value: new _retryingqueue2.default() },
_onRemoveMap: { value: onRemoveMap },

@@ -683,2 +684,3 @@ _links: { get: function get() {

this._onRemoveMap(this.sid);
return this._deps.network.delete(this.uri).then(function () {

@@ -693,7 +695,2 @@ _this13.emit('collectionRemoved', true);

}
}, {
key: 'lastEventId',
get: function get() {
return this._lastEventId;
}
}]);

@@ -700,0 +697,0 @@ return SyncMap;

{
"name": "twilio-sync",
"version": "0.3.1-alpha.2",
"version": "0.3.1",
"description": "Twilio Sync client library",

@@ -19,5 +19,5 @@ "main": "lib/index.js",

"platform": "^1.3.1",
"twilio-notifications": "^0.2.0-alpha",
"twilio-notifications": "^0.2.0",
"twilio-transport": "^0.0.8",
"twilsock": "^0.2.0-alpha",
"twilsock": "^0.2.0",
"uuid": "^2.0.2"

@@ -24,0 +24,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc