UNPKG

@hprose/rpc-plugin-push

Version:
345 lines 14.6 kB
"use strict"; /*--------------------------------------------------------*\ | | | hprose | | | | Official WebSite: https://hprose.com | | | | Broker.ts | | | | Broker for TypeScript. | | | | LastModified: Jun 14, 2021 | | Author: Ma Bingyao <andot@hprose.com> | | | \*________________________________________________________*/ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Broker = void 0; var rpc_core_1 = require("@hprose/rpc-core"); var Message_1 = require("./Message"); var Broker = /** @class */ (function () { function Broker(service) { var _this = this; this.service = service; this.messages = Object.create(null); this.responders = Object.create(null); this.timers = Object.create(null); this.messageQueueMaxLength = 10; this.timeout = 120000; this.heartbeat = 10000; this.handler = function (name, args, context, next) { return __awaiter(_this, void 0, void 0, function () { var from, producer; var _this = this; return __generator(this, function (_a) { from = (context.requestHeaders['id']) ? context.requestHeaders['id'].toString() : ''; switch (name) { case '>': case '>?': if (args.length === 3) args.push(from); break; case '>*': if (args.length === 2) args.push(from); break; } producer = { from: from, unicast: function (data, topic, id) { return _this.unicast(data, topic, id, from); }, multicast: function (data, topic, ids) { return _this.multicast(data, topic, ids, from); }, broadcast: function (data, topic) { return _this.broadcast(data, topic, from); }, push: function (data, topic, id) { return _this.push(data, topic, id, from); }, deny: function (id, topic) { if (id === void 0) { id = from; } return _this.deny(id, topic); }, exists: function (topic, id) { if (id === void 0) { id = from; } return _this.exists(topic, id); }, idlist: function (topic) { return _this.idlist(topic); } }; context.producer = producer; return [2 /*return*/, next(name, args, context)]; }); }); }; var subscribe = new rpc_core_1.Method(this.subscribe, '+', this, [String]); subscribe.passContext = true; var unsubscribe = new rpc_core_1.Method(this.unsubscribe, '-', this, [String]); unsubscribe.passContext = true; var message = new rpc_core_1.Method(this.message, '<', this); message.passContext = true; var unicast = new rpc_core_1.Method(this.unicast, '>', this, [undefined, String, String, String]); var multicast = new rpc_core_1.Method(this.multicast, '>?', this, [undefined, String, Array, String]); var broadcast = new rpc_core_1.Method(this.broadcast, '>*', this, [undefined, String, String]); var exists = new rpc_core_1.Method(this.exists, '?', this, [String, String]); var idlist = new rpc_core_1.Method(this.idlist, '|', this, [String]); this.service.add(subscribe) .add(unsubscribe) .add(message) .add(unicast) .add(multicast) .add(broadcast) .add(exists) .add(idlist) .use(this.handler); } Broker.prototype.send = function (id, responder) { var topics = this.messages[id]; if (topics) { var result = Object.create(null); var count = 0; var size = 0; for (var topic in topics) { ++size; var messages = topics[topic]; if (messages === null || messages.length > 0) { ++count; result[topic] = messages; if (messages === null) { delete topics[topic]; } else { topics[topic] = []; } } } if (size === 0) { responder.resolve(); } else if (count > 0) { responder.resolve(result); this.doHeartbeat(id); } else { return false; } } else { responder.resolve(); } return true; }; Broker.prototype.doHeartbeat = function (id) { var _this = this; if (this.heartbeat > 0) { var timer_1 = rpc_core_1.defer(); if (this.timers[id]) { this.timers[id].resolve(false); } this.timers[id] = timer_1; var timeoutId_1 = setTimeout(function () { timer_1.resolve(true); }, this.heartbeat); timer_1.promise.then(function (value) { clearTimeout(timeoutId_1); var topics = _this.messages[id]; if (value && topics) { for (var topic in topics) { _this.offline(topics, id, topic, new rpc_core_1.ServiceContext(_this.service)); } } }); } }; Broker.prototype.id = function (context) { if (context.requestHeaders['id']) { return context.requestHeaders['id'].toString(); } throw new Error('Client unique id not found'); }; Broker.prototype.subscribe = function (topic, context) { var id = this.id(context); if (this.messages[id] === undefined) { this.messages[id] = Object.create(null); } if (this.messages[id][topic]) { return false; } this.messages[id][topic] = []; if (this.onsubscribe) { this.onsubscribe(id, topic, context); } return true; }; Broker.prototype.response = function (id) { if (this.responders[id]) { var responder = this.responders[id]; delete this.responders[id]; if (!this.send(id, responder)) { if (id in this.responders) { responder.resolve(); } else { this.responders[id] = responder; } } } }; Broker.prototype.offline = function (topics, id, topic, context) { if (topic in topics) { var messages = topics[topic]; delete topics[topic]; if (this.onunsubscribe) { this.onunsubscribe(id, topic, messages, context); } this.response(id); return true; } return false; }; Broker.prototype.unsubscribe = function (topic, context) { var id = this.id(context); if (this.messages[id]) { return this.offline(this.messages[id], id, topic, context); } return false; }; Broker.prototype.message = function (context) { return __awaiter(this, void 0, void 0, function () { var id, responder_1, timer, responder, timeoutId_2; var _this = this; return __generator(this, function (_a) { id = this.id(context); if (this.responders[id]) { responder_1 = this.responders[id]; delete this.responders[id]; responder_1.resolve(); } if (this.timers[id]) { timer = this.timers[id]; delete this.timers[id]; timer.resolve(false); } responder = rpc_core_1.defer(); if (!this.send(id, responder)) { this.responders[id] = responder; if (this.timeout > 0) { timeoutId_2 = setTimeout(function () { if (_this.responders[id] === responder) { responder.resolve(Object.create(null)); } _this.doHeartbeat(id); }, this.timeout); responder.promise.then(function () { clearTimeout(timeoutId_2); }); } } return [2 /*return*/, responder.promise]; }); }); }; Broker.prototype.unicast = function (data, topic, id, from) { if (from === void 0) { from = ''; } if (this.messages[id]) { var messages = this.messages[id][topic]; if (messages && messages.length < this.messageQueueMaxLength) { messages.push(new Message_1.Message(data, from)); this.response(id); return true; } } return false; }; Broker.prototype.multicast = function (data, topic, ids, from) { if (from === void 0) { from = ''; } var result = Object.create(null); for (var i = 0; i < ids.length; ++i) { result[ids[i]] = this.unicast(data, topic, ids[i], from); } return result; }; Broker.prototype.broadcast = function (data, topic, from) { if (from === void 0) { from = ''; } var result = Object.create(null); for (var id in this.messages) { var messages = this.messages[id][topic]; if (messages) { if (messages.length < this.messageQueueMaxLength) { messages.push(new Message_1.Message(data, from)); this.response(id); result[id] = true; } else { result[id] = false; } } } return result; }; Broker.prototype.push = function (data, topic, id, from) { if (from === void 0) { from = ''; } switch (typeof id) { case 'undefined': return this.broadcast(data, topic, from); case 'string': return this.unicast(data, topic, id, from); default: return this.multicast(data, topic, id, from); } }; Broker.prototype.deny = function (id, topic) { if (this.messages[id]) { if (topic) { if (topic in this.messages[id]) { this.messages[id][topic] = null; } } else { for (var topic_1 in this.messages[id]) { this.messages[id][topic_1] = null; } } this.response(id); } }; Broker.prototype.exists = function (topic, id) { return (id in this.messages) && Array.isArray(this.messages[id][topic]); }; Broker.prototype.idlist = function (topic) { var idlist = []; for (var id in this.messages) { if (this.messages[id][topic]) { idlist.push(id); } } return idlist; }; return Broker; }()); exports.Broker = Broker; //# sourceMappingURL=Broker.js.map