Skip to content

Instantly share code, notes, and snippets.

@igordata
Created February 10, 2018 14:08
Show Gist options
  • Save igordata/c2be98b75f2f713b078820ec14e8de24 to your computer and use it in GitHub Desktop.
Save igordata/c2be98b75f2f713b078820ec14e8de24 to your computer and use it in GitHub Desktop.
centrifugo web worker
console.log('ww starting');
function wwsClass() {
var wws = this;
wws.tabs = [];
wws.onconnect = function (e) {
for (var i = e.ports.length; i--;) {
wws.tabs.push(new wwsTab(e.ports[i]));
}
console.log('New tabs ' + e.ports.length);
console.log(wws.tabs);
};
wws.broadcast = function (msg) {
console.log("Broadcasting message to " + wws.tabs.length + "tabss.");
console.log(msg);
for (var i = wws.tabs.length; i--;) {
try {
wws.tabs[i].send(msg);
} catch (e) {
wws.tabs[i].close();
}
}
};
wws.sendToRandom = function (msg) {
var tab = Math.floor(Math.random() * wws.tabs.length);
console.log("Sending message to " + tab + " tab.");
console.log(msg);
try {
wws.tabs[tab].send(msg);
} catch (e) {
wws.tabs[tab].close();
}
};
function wwsTab(port) {
console.log('New tab', port);
var tab = this;
tab.port = port;
tab.channels = [];
tab.send = function (msg) {
tab.port.postMessage(msg);
};
tab.port.onmessage = function (e) {
tab.onTabMessage(e.data);
};
tab.onTabMessage = function (msg) {
//console.log('Tab message: ', msg);
if (!msg.type) {
return false;
}
switch (msg.type) {
case 'command':
tab.onTabCommand(msg.command, msg.data);
break;
case 'message':
console.log(msg.data);
break;
}
};
tab.onTabCommand = function (command, data) {
switch (command) {
case 'ping':
console.log('tab ping received');
break;
case 'subscribe':
tab.commands.subscribe(data);
break;
case 'bye':
console.log('Tab closing');
wws.onTabClose(tab);
break;
}
};
tab.commands = {
subscribe: function (channels) {
console.log('Tab want to subscribe to channels: ', channels);
if (typeof channels === 'undefined') {
return false;
}
if (channels.length == 0) {
return false;
}
for (var i = channels.length; i--;) {
tab.channels.push(channels[i]);
}
tab.channels = tab.channels.filter(function (item, pos, self) {
return self.indexOf(item) == pos;
});
wws.subscribe(channels);
}
};
console.log(tab);
}
wws.onTabClose = function (tab) {
wws.channels.unsub(tab.channels);
console.log('closing tab port');
wws.tabs.splice(wws.tabs.indexOf(tab), 1);
console.log(wws.tabs);
if (wws.tabs.length === 0) {
wws.onGoodbye();
}
};
wws.onGoodbye = function () {
console.log('Bye! Have a good time!');
};
wws.notice = function (options) {
if (typeof options !== 'object') {
options = {text: options};
}
var defaults = {
html: false,
header: false,
text: '',
type: 'info',
image: false,
url: false
};
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
var settings = extend({}, defaults, options);
if (typeof Notification !== 'undefined') {
try {
var notification = new Notification(settings.header, {
icon: settings.image,
body: settings.text
});
notification.onclick = function (e) {
console.log('Notice clicked');
console.log(e);
wws.sendToRandom({type: 'navigate', data: {url: settings.url}});
notification.close();
};
notification.onclose = function () {
console.log('Notice closed');
};
} catch (err) {
}
}
};
wws.processOptions = function (options) {
for (var key in options) {
switch (key) {
case 'notice':
if ((Notification.permission === "granted")) {
/* permission granted, рисуем сами, отрезаем нотис, чтобы из браузера со странички он не рисовался уже */
wws.notice(options['notice']);
delete options['notice'];
}
break;
}
}
return options;
};
wws.callbacks = {
"message": function (msg) {
console.log(msg);
msg = msg.data;
if (typeof msg.options !== 'undefined') {
msg.options = wws.processOptions(msg.options);
}
console.log('sending message', msg);
wws.broadcast(msg);
},
"join": function (message) {
console.log('join', message);
},
"leave": function (message) {
console.log('leave', message);
},
"subscribe": function (context) {
console.log('subscribe', context);
},
"error": function (error) {
console.log('error', error);
},
"unsubscribe": function (context) {
console.log('unsubscribe', context);
if (wws.channels.list.hasOwnProperty(context.channel)) {
delete wws.channels.list[context.channel];
}
console.log(wws.channels.list);
}
};
wws.channels = new ChannelsList();
function ChannelsList() {
var cl = this;
cl.list = {};
cl.sub = function (channels) {
if (typeof channels === 'undefined') {
return false;
}
if (channels.length == 0) {
return false;
}
for (var i = channels.length; i--;) {
if (!cl.list.hasOwnProperty(channels[i])) {
cl.list[channels[i]] = {counter: 0, subscription: false};
}
cl.list[channels[i]].counter++;
}
console.log('Current channels list: ', cl.list);
};
cl.unsub = function (channels) {
console.log(channels);
if (typeof channels === 'undefined') {
return false;
}
if (channels.length == 0) {
return false;
}
for (var i = channels.length; i--;) {
if (!cl.list.hasOwnProperty(channels[i])) {
// already unsubcribed, but how is it possible?
}
cl.list[channels[i]].counter--;
}
var abandoned = [];
for (var chan in cl.list) {
if (cl.list[chan].counter < 1) {
abandoned.push(chan);
}
}
console.log('Abandoned channels list: ', abandoned);
// тут надо кильнуть абандонед
cl.kill(abandoned);
console.log('Current channels list: ', cl.list);
};
cl.kill = function (channels) {
if (typeof channels === 'undefined') {
return false;
}
if (channels.length == 0) {
return false;
}
wws.centrifuge.startAuthBatching();
for (var i = channels.length; i--;) {
if (cl.list.hasOwnProperty(channels[i])) {
console.log('Closing channel ' + channels[i]);
cl.list[channels[i]].subscription.unsubscribe();
}
}
wws.centrifuge.stopAuthBatching();
};
};
wws.subscribe = function (channels) {
wws.channels.sub(channels);
console.log('Want to subscribe to: ', channels);
console.log('Current channels list: ', wws.channels.list);
if (!wws.centrifuge) {
console.log("can't subscribe now, maybe later");
return false;
}
console.log('Subscribing');
wws.centrifuge.startAuthBatching();
for (var chan in wws.channels.list) {
if (wws.channels.list[chan].subscription == false) {
/* не подписаны, надо подписаться */
wws.channels.list[chan].subscription = wws.centrifuge.subscribe(chan, wws.callbacks);
}
}
wws.centrifuge.stopAuthBatching();
};
wws.centrifuge = null;
wws.init = function () {
var data = [];
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", '/api/rtm/subscribe');
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
console.log('Response: ' + xmlhttp.responseText);
var reply = ajaxResponseParse(xmlhttp.responseText);
console.log(reply);
wws.centrifuge = new Centrifuge({
/*debug: true,*/
url: '/centrifugo',
user: reply.getData('user'),
timestamp: reply.getData('timestamp'),
token: reply.getData('token'),
authEndpoint: '/api/rtm/auth',
transports: ['websocket', 'xdr-streaming', 'xhr-streaming', 'eventsource', 'xdr-polling', 'xhr-polling', 'jsonp-polling']
});
wws.subscribe(reply.getData('channels'));
wws.centrifuge.connect();
} else {
console.log('Error: ' + xmlhttp.statusText)
}
}
};
xmlhttp.send(data);
};
}
var worker = new wwsClass();
console.log('ww created');
onconnect = worker.onconnect;
console.log('2');
/*setInterval(function () {
worker.broadcast("time: " + (new Date().getTime()));
}, 5000);*/
console.log('3');
importScripts(
"/rtm/ajaxresponse.js",
"/rtm/sockjs.js"
);
importScripts("/rtm/centrifugo.js");
console.log('worker.init();');
worker.init();
console.log('waiting for messages');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment