2021-12-29 00:19:22 -05:00
|
|
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
|
|
if (gapp.broker) return;
|
|
|
|
|
|
2021-12-29 12:55:45 -05:00
|
|
|
gapp.register('moto.broker');
|
|
|
|
|
|
|
|
|
|
gapp.broker = new class Broker {
|
2021-12-08 22:09:07 -05:00
|
|
|
constructor() {
|
|
|
|
|
this.topics = {};
|
2021-12-29 00:19:22 -05:00
|
|
|
this.used = {};
|
2021-12-29 00:36:04 -05:00
|
|
|
this.send = {};
|
2021-12-08 22:09:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
topics() {
|
|
|
|
|
return Object.keys(this.topics);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subscribe(topic, listener) {
|
2021-12-14 21:26:40 -05:00
|
|
|
if (Array.isArray(topic)) {
|
|
|
|
|
for (let t of topic) {
|
|
|
|
|
this.subscribe(t, listener);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-12-08 22:09:07 -05:00
|
|
|
let topics = this.topics;
|
|
|
|
|
let channel = topics[topic];
|
|
|
|
|
if (!channel) {
|
|
|
|
|
channel = topics[topic] = [];
|
|
|
|
|
}
|
|
|
|
|
if (channel.indexOf(listener) < 0) {
|
2021-12-29 00:36:04 -05:00
|
|
|
let send = this.send;
|
2021-12-29 07:54:16 -05:00
|
|
|
let name = topic.replace(/[\\ \.-]/g, '_');
|
2021-12-29 00:36:04 -05:00
|
|
|
send[name] = send[name] = this.bind(topic);
|
2021-12-08 22:09:07 -05:00
|
|
|
channel.push(listener);
|
|
|
|
|
this.publish(".topic.add", topic);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsubscribe(topic, listener) {
|
|
|
|
|
let channel = this.topics[topic];
|
|
|
|
|
if (!channel) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let index = channel.indexOf(listener);
|
|
|
|
|
if (index < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
channel.splice(index,1);
|
|
|
|
|
if (channel.length === 0) {
|
|
|
|
|
delete this.topics[topic];
|
|
|
|
|
this.publish(".topic.remove", topic);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
publish(topic, message, options = {}) {
|
2021-12-14 21:26:40 -05:00
|
|
|
if (Array.isArray(topic)) {
|
|
|
|
|
for (let t of topic) {
|
|
|
|
|
this.publish(t, message, options);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-12-08 22:09:07 -05:00
|
|
|
if (topic !== ".topic.publish") {
|
|
|
|
|
this.publish(".topic.publish", {topic, message, options});
|
|
|
|
|
}
|
2021-12-29 00:19:22 -05:00
|
|
|
// store last seen message on a topic
|
|
|
|
|
// acts as a tracker for all used topics
|
|
|
|
|
this.used[topic] = message;
|
2021-12-08 22:09:07 -05:00
|
|
|
let channel = this.topics[topic];
|
|
|
|
|
if (channel && channel.length) {
|
|
|
|
|
for (let listener of channel) {
|
2021-12-14 21:26:40 -05:00
|
|
|
try {
|
|
|
|
|
listener(message, topic, options);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// console.log({listener_error: e, topic, options, listener});
|
|
|
|
|
setTimeout(() => { throw e }, 1);
|
|
|
|
|
}
|
2021-12-08 22:09:07 -05:00
|
|
|
}
|
2021-12-29 00:19:22 -05:00
|
|
|
} else if (topic.indexOf(".topic.") < 0) {
|
|
|
|
|
dbug.debug(`undelivered '${topic}'`, message);
|
2021-12-08 22:09:07 -05:00
|
|
|
}
|
2022-01-01 12:12:57 -05:00
|
|
|
return message;
|
2021-12-08 22:09:07 -05:00
|
|
|
}
|
2021-12-09 21:55:16 -05:00
|
|
|
|
|
|
|
|
// return function bound to a topic
|
|
|
|
|
bind(topic, message, options) {
|
|
|
|
|
let broker = this;
|
2021-12-09 23:12:35 -05:00
|
|
|
return function(msg, opt) {
|
|
|
|
|
broker.publish(topic, message || msg, options || opt);
|
2021-12-09 21:55:16 -05:00
|
|
|
}
|
|
|
|
|
}
|
2022-01-01 12:12:57 -05:00
|
|
|
|
|
|
|
|
// return function wrapper that publishes a message to a topic
|
|
|
|
|
wrap(topic, fn) {
|
|
|
|
|
let broker = this;
|
|
|
|
|
return function() {
|
|
|
|
|
return broker.publish(topic, fn(...arguments));
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-08 22:09:07 -05:00
|
|
|
}
|
2021-12-27 20:39:07 -05:00
|
|
|
|
2021-12-29 00:19:22 -05:00
|
|
|
})();
|