1 | 'use strict'
|
2 |
|
3 | const Promise = require('bluebird')
|
4 | const _ = require('lodash')
|
5 | const hasBinary = require('has-binary')
|
6 | const { EventEmitter } = require('events')
|
7 |
|
8 |
|
9 | const EVENT = 2
|
10 | const BINARY_EVENT = 5
|
11 |
|
12 |
|
13 | class 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 |
|
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 |
|
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 |
|
87 | module.exports = SocketIOClusterBus
|