proteus-js-client
Version:
Proteus JavaScript Client
297 lines (236 loc) • 10 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _rsocketTypes = require('rsocket-types');
var _rsocketFlowable = require('rsocket-flowable');
var _rsocketCore = require('rsocket-core');
var _rsocketRpcCore = require('rsocket-rpc-core');
var _invariant = require('fbjs/lib/invariant');
var _invariant2 = _interopRequireDefault(_invariant);
var _rsocket = require('./rsocket');
var _frames = require('./frames');
var _rsocketWebsocketClient = require('rsocket-websocket-client');
var _rsocketWebsocketClient2 = _interopRequireDefault(_rsocketWebsocketClient);
var _ConnectionId = require('./frames/ConnectionId');
var _ConnectionId2 = _interopRequireDefault(_ConnectionId);
var _AdditionalFlags = require('./frames/AdditionalFlags');
var _AdditionalFlags2 = _interopRequireDefault(_AdditionalFlags);
var _v = require('uuid/v4');
var _v2 = _interopRequireDefault(_v);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Copyright (c) 2017-present, Netifi Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
'use-strict';
var Proteus = function () {
function Proteus(group, tags, proteusClient, requestHandler) {
var _this = this;
_classCallCheck(this, Proteus);
this._client = proteusClient;
this._group = group;
this._tags = tags;
this._connect = function () {
if (_this._connection) {
return _rsocketFlowable.Single.of(_this._connection);
} else if (_this._connecting) {
return new _rsocketFlowable.Single(function (subscriber) {
_this._connecting.subscribe(subscriber);
});
} else {
/** * This is a useful Publisher implementation that wraps could feasibly wrap the Single type ** */
/** * Might be useful to clean up and contribute back or put in a utility or something ** */
_this._connecting = function () {
var _subscribers = [];
var _connection = void 0;
var _error = void 0;
var _completed = false;
return {
onComplete: function onComplete(connection) {
// Memoize for future subscribers
_completed = true;
_connection = connection;
_subscribers.map(function (subscriber) {
if (subscriber.onComplete) {
subscriber.onComplete(connection);
}
});
},
onError: function onError(error) {
_completed = true;
_error = error;
_subscribers.map(function (subscriber) {
if (subscriber.onError) {
subscriber.onError(error);
}
});
},
onSubscribe: function onSubscribe(cancel) {
_subscribers.map(function (subscriber) {
if (subscriber.onSubscribe) {
subscriber.onSubscribe(cancel);
}
});
},
subscribe: function subscribe(subscriber) {
if (_completed) {
subscriber.onSubscribe();
subscriber.onComplete(_connection);
} else if (_error) {
subscriber.onSubscribe();
subscriber.onError(_error);
} else {
_subscribers.push(subscriber);
if (subscriber.onSubscribe) {
subscriber.onSubscribe(function () {
var idx = _subscribers.indexOf(subscriber);
if (idx > -1) {
_subscribers.splice(idx, 1);
}
});
}
}
}
};
}();
_this._connecting.subscribe({
onComplete: function onComplete(connection) {
_this._connection = connection;
},
onError: function onError(err) {
console.warn('An error has occurred while connecting:');
console.warn(err);
},
onSubscribe: function onSubscribe(cancel) {
// do nothing
}
});
setTimeout(function () {
return proteusClient.connect().subscribe(_this._connecting);
}, _this.calculateRetryDuration());
return _this._connecting;
}
};
this._requestHandler = requestHandler;
}
Proteus.prototype.myGroup = function myGroup() {
return this._group;
};
Proteus.prototype.myTags = function myTags() {
return this._tags;
};
Proteus.prototype.broadcast = function broadcast(group, tags) {
return _rsocket.DeferredConnectingRSocket.broadcast(group, tags, this._connect);
};
Proteus.prototype.group = function (_group) {
function group(_x, _x2) {
return _group.apply(this, arguments);
}
group.toString = function () {
return _group.toString();
};
return group;
}(function (group, tags) {
return _rsocket.DeferredConnectingRSocket.group(group, tags, this._connect);
});
Proteus.prototype.destination = function (_destination) {
function destination(_x3, _x4) {
return _destination.apply(this, arguments);
}
destination.toString = function () {
return _destination.toString();
};
return destination;
}(function (destination, group) {
return _rsocket.DeferredConnectingRSocket.group(group, { 'com.netifi.destination': destination }, this._connect);
});
Proteus.prototype.addService = function addService(service, handler) {
this._requestHandler.addService(service, handler);
};
Proteus.prototype.close = function close() {
this._client.close();
};
Proteus.prototype.calculateRetryDuration = function calculateRetryDuration() {
var currentTs = Date.now();
var oldTs = this._lastConnectionAttemptTs || 0;
var calculatedDuration = Math.min(this._attempts, 30);
if (currentTs - oldTs > 60000) {
this._attempts = 0;
}
this._lastConnectionAttemptTs = currentTs;
this._attempts++;
return calculatedDuration * 1000;
};
Proteus.create = function create(config) {
(0, _invariant2.default)(config && config.setup && config.setup.accessKey && config.setup.accessToken && config.transport, 'Proteus: Falsey config is invalid. At minimum transport config, group, access key, and access token are required.');
(0, _invariant2.default)(config.transport.connection || config.transport.url, 'Proteus: Transport config must supply a connection or a URL');
// default to GUID-y destination ID
var destination = config.setup.destination !== undefined ? config.setup.destination : (0, _v2.default)();
var tags = config.setup.tags !== undefined ? _extends({ 'com.netifi.destination': destination }, config.setup.tags) : { 'com.netifi.destination': destination };
var keepAlive = config.setup.keepAlive !== undefined ? config.setup.keepAlive : 60000; /* 60s in ms */
var lifetime = config.setup.lifetime !== undefined ? config.setup.lifetime : 360000; /* 360s in ms */
var accessKey = config.setup.accessKey;
var accessToken = Buffer.from(config.setup.accessToken, 'base64');
/* If a connectionId is not provided, seed it */
var connectionIdSeed = typeof config.setup.connectionId !== 'undefined' ? config.setup.connectionId : Date.now().toString();
var connectionId = new _ConnectionId2.default(connectionIdSeed);
var additionalFlagsLiteral = _extends({
public: false
}, config.setup.additionalFlags);
var additionalFlags = new _AdditionalFlags2.default(additionalFlagsLiteral);
var transport = config.transport.connection !== undefined ? config.transport.connection : new _rsocketWebsocketClient2.default({
url: config.transport.url ? config.transport.url : 'ws://',
wsCreator: config.transport.wsCreator
}, _rsocketCore.BufferEncoders);
var requestHandler = new _rsocketRpcCore.RequestHandlingRSocket();
var responder = new _rsocket.UnwrappingRSocket(requestHandler);
var metadata = (0, _frames.encodeFrame)({
type: _frames.FrameTypes.DESTINATION_SETUP,
majorVersion: null,
minorVersion: null,
group: config.setup.group,
tags: tags,
accessKey: accessKey,
accessToken: accessToken,
connectionId: connectionId,
additionalFlags: additionalFlags
});
var finalConfig = {
setup: {
keepAlive: keepAlive,
lifetime: lifetime,
metadata: metadata,
connectionId: connectionId,
additionalFlags: additionalFlags
},
transport: transport,
responder: responder
};
if (config.responder !== undefined) {
finalConfig.responder = config.responder;
}
if (config.serializers !== undefined) {
finalConfig.serializers = config.serializers;
}
var client = new _rsocketRpcCore.RpcClient(finalConfig);
return new Proteus(config.setup.group, tags, client, requestHandler);
};
return Proteus;
}();
exports.default = Proteus;