@hprose/rpc-plugin-push
Version:
345 lines • 14.6 kB
JavaScript
"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