UNPKG

2.33 kBJavaScriptView Raw
1'use strict'
2
3const Promise = require('bluebird')
4const _ = require('lodash')
5const hasBinary = require('has-binary')
6const { EventEmitter } = require('events')
7
8// from socket.io-protocol v4
9const EVENT = 2
10const BINARY_EVENT = 5
11
12// Instances communication via a socket.io-adapter implementation.
13class SocketIOClusterBus extends EventEmitter {
14
15 constructor (server, adapter) {
16 super()
17 this.server = server
18 this.adapter = adapter
19 this.channel = 'cluster:bus'
20 this.intenalEvents = [ 'roomLeaveSocket',
21 'socketRoomLeft',
22 'disconnectUserSockets' ]
23 this.types = [ EVENT, BINARY_EVENT ]
24 this.injectBusHook()
25 }
26
27 listen () {
28 return Promise.fromCallback(cb => {
29 return this.adapter.add(this.server.instanceUID, this.channel, cb)
30 })
31 }
32
33 makeSocketRoomLeftName (id, roomName) {
34 return `socketRoomLeft:${id}:${roomName}`
35 }
36
37 mergeEventName (ev, args) {
38 switch (ev) {
39 case 'socketRoomLeft':
40 let [id, roomName, ...nargs] = args
41 let nev = this.makeSocketRoomLeftName(id, roomName)
42 return [nev, nargs]
43 default:
44 return [ev, args]
45 }
46 }
47
48 // TODO: Use an API from socket.io if(when) it will be available.
49 emit (ev, ...args) {
50 let data = [ ev, ...args ]
51 let packet = { type: (hasBinary(args) ? BINARY_EVENT : EVENT), data }
52 let opts = { rooms: [ this.channel ] }
53 this.adapter.broadcast(packet, opts, false)
54 }
55
56 onPacket (packet) {
57 let [ev, ...args] = packet.data
58 if (_.includes(this.intenalEvents, ev)) {
59 let [nev, nargs] = this.mergeEventName(ev, args)
60 return super.emit(nev, ...nargs)
61 } else {
62 return super.emit(ev, ...args)
63 }
64 }
65
66 broadcastHook (packet, opts) {
67 let isBusCahnnel = _.includes(opts.rooms, this.channel)
68 let isBusType = _.includes(this.types, packet.type)
69 if (isBusCahnnel && isBusType) {
70 this.onPacket(packet)
71 }
72 }
73
74 // TODO: Use an API from socket.io if(when) it will be available.
75 injectBusHook () {
76 let broadcastHook = this.broadcastHook.bind(this)
77 let adapter = this.adapter
78 let orig = this.adapter.broadcast
79 adapter.broadcast = function (...args) {
80 broadcastHook(...args)
81 orig.apply(adapter, args)
82 }
83 }
84
85}
86
87module.exports = SocketIOClusterBus