cloudcms-server 0.9.261 → 0.9.262
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/framework/controllers.js +4 -4
- package/launchpad/index.js +13 -0
- package/launchpad/launchers/cluster.js +23 -5
- package/launchpad/launchers/redis.js +47 -16
- package/launchpad/launchers/single.js +6 -0
- package/middleware/authentication/providers/saml.js +0 -1
- package/middleware/awareness/awareness.js +39 -27
- package/middleware/awareness/providers/abstract-async.js +109 -70
- package/middleware/awareness/providers/abstract.js +1 -1
- package/middleware/awareness/providers/memory.js +0 -14
- package/middleware/awareness/providers/redis.js +113 -232
- package/package.json +1 -1
- package/server/index.js +2 -4
- package/web/socket.io/socket.io.js +0 -4240
package/framework/controllers.js
CHANGED
|
@@ -163,10 +163,10 @@ var handleInvalidate = function(req, res)
|
|
|
163
163
|
// new timestamp
|
|
164
164
|
process.env.CLOUDCMS_APPSERVER_TIMESTAMP = new Date().getTime();
|
|
165
165
|
|
|
166
|
-
// update all socket clients
|
|
167
|
-
process.IO.sockets.emit("timestamp", {
|
|
168
|
-
|
|
169
|
-
});
|
|
166
|
+
// // update all socket clients
|
|
167
|
+
// process.IO.sockets.emit("timestamp", {
|
|
168
|
+
// "timestamp": process.env.CLOUDCMS_APPSERVER_TIMESTAMP
|
|
169
|
+
// });
|
|
170
170
|
|
|
171
171
|
console.log("Server timestamp regenerated");
|
|
172
172
|
|
package/launchpad/index.js
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
const cluster = require("cluster");
|
|
2
2
|
|
|
3
|
+
// Handle uncaught exceptions...
|
|
4
|
+
process.on('uncaughtException', function(err, source) {
|
|
5
|
+
// if (err === "read ECONNRESET")
|
|
6
|
+
// {
|
|
7
|
+
// // skip
|
|
8
|
+
// }
|
|
9
|
+
// else
|
|
10
|
+
// {
|
|
11
|
+
console.log(`Launchpad - process received event 'uncaughtException': ${err}, source: ${source}`);
|
|
12
|
+
console.log(err.stack);
|
|
13
|
+
// }
|
|
14
|
+
});
|
|
15
|
+
|
|
3
16
|
module.exports = function(type, config, options)
|
|
4
17
|
{
|
|
5
18
|
if (!type) {
|
|
@@ -6,6 +6,9 @@ const numCPUs = require("os").cpus().length;
|
|
|
6
6
|
const { setupMaster, setupWorker } = require("@socket.io/sticky");
|
|
7
7
|
const { createAdapter, setupPrimary } = require("@socket.io/cluster-adapter");
|
|
8
8
|
|
|
9
|
+
// numCPUs = 1;
|
|
10
|
+
// console.log("FORCE ONE CPU");
|
|
11
|
+
|
|
9
12
|
module.exports = function(config) {
|
|
10
13
|
|
|
11
14
|
var r = {};
|
|
@@ -14,7 +17,7 @@ module.exports = function(config) {
|
|
|
14
17
|
{
|
|
15
18
|
// setup sticky sessions
|
|
16
19
|
setupMaster(httpServer, {
|
|
17
|
-
loadBalancingMethod: "least-connection"
|
|
20
|
+
loadBalancingMethod: "least-connection"
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
// setup connections between the workers
|
|
@@ -46,14 +49,23 @@ module.exports = function(config) {
|
|
|
46
49
|
var worker = cluster.fork(workerEnv);
|
|
47
50
|
|
|
48
51
|
worker.on('message', function (msg, c) {
|
|
52
|
+
//console.log("Worker message: " + msg + ", c: " + c);
|
|
49
53
|
if (msg === "worker-startup") {
|
|
50
54
|
startupCount++;
|
|
51
55
|
}
|
|
52
56
|
});
|
|
53
57
|
|
|
58
|
+
worker.on('error', function(err) {
|
|
59
|
+
console.log("Worker.on(error) - " + JSON.stringify(err));
|
|
60
|
+
});
|
|
61
|
+
|
|
54
62
|
workers.push(worker);
|
|
55
63
|
}
|
|
56
64
|
|
|
65
|
+
cluster.on("error", function(err) {
|
|
66
|
+
console.log("Cluster.on(error) - " + JSON.stringify(err));
|
|
67
|
+
});
|
|
68
|
+
|
|
57
69
|
cluster.on("exit", (worker) => {
|
|
58
70
|
console.log(`Worker ${worker.process.pid} died`);
|
|
59
71
|
cluster.fork();
|
|
@@ -79,19 +91,25 @@ module.exports = function(config) {
|
|
|
79
91
|
// worker
|
|
80
92
|
|
|
81
93
|
const io = new Server(httpServer);
|
|
82
|
-
|
|
94
|
+
httpServer.io = io;
|
|
95
|
+
|
|
83
96
|
// use the cluster adapter
|
|
84
97
|
io.adapter(createAdapter());
|
|
85
98
|
|
|
86
99
|
// setup connection with the primary process
|
|
87
100
|
setupWorker(io);
|
|
88
|
-
|
|
101
|
+
|
|
102
|
+
// on connect
|
|
89
103
|
io.on("connection", (socket) => {
|
|
90
104
|
// TODO
|
|
105
|
+
|
|
106
|
+
// always catch err
|
|
107
|
+
socket.on("error", function(err) {
|
|
108
|
+
console.log("Caught socket error");
|
|
109
|
+
console.log(err.stack);
|
|
110
|
+
});
|
|
91
111
|
});
|
|
92
112
|
|
|
93
|
-
httpServer.io = io;
|
|
94
|
-
|
|
95
113
|
return callback();
|
|
96
114
|
};
|
|
97
115
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { Server } = require("socket.io");
|
|
2
2
|
const { setupWorker } = require("@socket.io/sticky");
|
|
3
|
-
const { createAdapter } = require("@socket.io/
|
|
3
|
+
const { createAdapter } = require("@socket.io/redis-adapter");
|
|
4
4
|
const redisHelper = require("../../util/redis");
|
|
5
5
|
|
|
6
6
|
const clusterLauncherFactory = require("./cluster");
|
|
@@ -23,30 +23,61 @@ module.exports = function(config) {
|
|
|
23
23
|
|
|
24
24
|
r.afterStartServer = function(app, httpServer, callback)
|
|
25
25
|
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
(async function() {
|
|
26
|
+
(async function(app, httpServer, callback) {
|
|
29
27
|
var redisOptions = redisHelper.redisOptions({}, "CLOUDCMS_CLUSTER");
|
|
30
28
|
await redisHelper.createAndConnect(redisOptions, function(err, _client) {
|
|
31
|
-
|
|
29
|
+
|
|
32
30
|
const pubClient = _client;
|
|
33
31
|
const subClient = pubClient.duplicate();
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
io.on("connection", (socket) => {
|
|
39
|
-
// TODO
|
|
32
|
+
|
|
33
|
+
pubClient.on("error", function(err) {
|
|
34
|
+
// something went wrong
|
|
35
|
+
console.log("Pub Client caught error: ", err);
|
|
40
36
|
});
|
|
41
|
-
|
|
37
|
+
|
|
38
|
+
subClient.on("error", function(err) {
|
|
39
|
+
// something went wrong
|
|
40
|
+
console.log("Sub Client caught error: ", err);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const io = new Server(httpServer);
|
|
44
|
+
httpServer.io = io;
|
|
45
|
+
|
|
46
|
+
io.engine.on("connection_error", function(err) {
|
|
47
|
+
// console.log("CONNECTION ERROR");
|
|
48
|
+
// console.log("REQUEST: " + err.req); // the request object
|
|
49
|
+
// console.log("CODE: " + err.code); // the error code, for example 1
|
|
50
|
+
// console.log("MESSAGE: " + err.message); // the error message, for example "Session ID unknown"
|
|
51
|
+
// console.log("CONTEXT: " + err.context); // some additional error context
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// use the redis adapter
|
|
55
|
+
io.adapter(createAdapter(pubClient, subClient, {
|
|
56
|
+
//publishOnSpecificResponseChannel: true
|
|
57
|
+
}));
|
|
58
|
+
|
|
42
59
|
// setup connection with the primary process
|
|
43
60
|
setupWorker(io);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
61
|
+
|
|
62
|
+
// on connect
|
|
63
|
+
io.on("connection", (socket) => {
|
|
64
|
+
//console.log("Redis Launcher on('connection') - socket id:" + socket.id);
|
|
65
|
+
// socket.on('message', function(m) {
|
|
66
|
+
// console.log("Socket Connection message: " + m);
|
|
67
|
+
// });
|
|
68
|
+
//
|
|
69
|
+
// // always catch err
|
|
70
|
+
// socket.on("error", function(err) {
|
|
71
|
+
// console.log("Caught socket error");
|
|
72
|
+
// console.log(err.stack);
|
|
73
|
+
// });
|
|
74
|
+
|
|
75
|
+
// TODO
|
|
76
|
+
});
|
|
77
|
+
|
|
47
78
|
return callback();
|
|
48
79
|
});
|
|
49
|
-
})();
|
|
80
|
+
})(app, httpServer, callback);
|
|
50
81
|
};
|
|
51
82
|
|
|
52
83
|
return r;
|
|
@@ -20,6 +20,12 @@ module.exports = function(config) {
|
|
|
20
20
|
|
|
21
21
|
io.on("connection", (socket) => {
|
|
22
22
|
// TODO
|
|
23
|
+
|
|
24
|
+
// always catch err
|
|
25
|
+
socket.on("error", function(err) {
|
|
26
|
+
console.log("Caught socket error");
|
|
27
|
+
console.log(err.stack);
|
|
28
|
+
});
|
|
23
29
|
});
|
|
24
30
|
|
|
25
31
|
httpServer.io = io;
|
|
@@ -60,10 +60,15 @@ exports = module.exports = function()
|
|
|
60
60
|
if (!process.configuration.awareness.config) {
|
|
61
61
|
process.configuration.awareness.config = {};
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
|
+
// init any plugins?
|
|
65
|
+
if (!process.configuration.awareness.plugins) {
|
|
66
|
+
process.configuration.awareness.plugins = [];
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
var type = process.configuration.awareness.type;
|
|
65
70
|
var config = process.configuration.awareness.config;
|
|
66
|
-
|
|
71
|
+
|
|
67
72
|
var providerFactory = require("./providers/" + type);
|
|
68
73
|
provider = new providerFactory(config);
|
|
69
74
|
|
|
@@ -74,12 +79,6 @@ exports = module.exports = function()
|
|
|
74
79
|
return callback(err);
|
|
75
80
|
}
|
|
76
81
|
|
|
77
|
-
// init any plugins?
|
|
78
|
-
if (!process.configuration.awareness.plugins) {
|
|
79
|
-
process.configuration.awareness.plugins = [];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
82
|
var fns = [];
|
|
84
83
|
for (var i = 0; i < pluginPaths.length; i++)
|
|
85
84
|
{
|
|
@@ -115,15 +114,18 @@ exports = module.exports = function()
|
|
|
115
114
|
/**
|
|
116
115
|
* This gets called whenever a new socket is connected to the Cloud CMS server.
|
|
117
116
|
*
|
|
117
|
+
* @param io
|
|
118
|
+
* @param callback
|
|
119
|
+
*
|
|
118
120
|
* @type {Function}
|
|
119
121
|
*/
|
|
120
|
-
var initSocketIO = r.initSocketIO = function(callback) {
|
|
121
|
-
|
|
122
|
+
var initSocketIO = r.initSocketIO = function(io, callback) {
|
|
123
|
+
|
|
122
124
|
// initialize socket IO event handlers so that awareness binds to any new, incoming sockets
|
|
123
|
-
socketInit(
|
|
125
|
+
socketInit(io);
|
|
124
126
|
|
|
125
127
|
// ensure the reaper is initialized
|
|
126
|
-
reaperInit(
|
|
128
|
+
reaperInit(io, REAP_FREQUENCY_MS, REAP_MAX_AGE_MS, function(err) {
|
|
127
129
|
callback(err);
|
|
128
130
|
});
|
|
129
131
|
};
|
|
@@ -172,7 +174,7 @@ exports = module.exports = function()
|
|
|
172
174
|
// when a socket.io connection is established, we set up some default listeners for events that the client
|
|
173
175
|
// may emit to us
|
|
174
176
|
io.on("connection", function(socket) {
|
|
175
|
-
|
|
177
|
+
|
|
176
178
|
// "register" -> indicates that a user is in a channel
|
|
177
179
|
socket.on("register", function(channelId, user, dirty, callback) {
|
|
178
180
|
|
|
@@ -193,24 +195,32 @@ exports = module.exports = function()
|
|
|
193
195
|
return callback(err);
|
|
194
196
|
}
|
|
195
197
|
|
|
196
|
-
// if we were already registered, just callback
|
|
197
|
-
// however, if "dirty" is set, then we always hand back membership
|
|
198
|
-
if (!dirty && alreadyRegistered)
|
|
199
|
-
{
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
198
|
+
// // if we were already registered, just callback
|
|
199
|
+
// // however, if "dirty" is set, then we always hand back membership
|
|
200
|
+
// if (!dirty && alreadyRegistered)
|
|
201
|
+
// {
|
|
202
|
+
// logger.info("Already registered, not dirty - channelId: " + channelId + ",userId=" + user.id + " (" + user.name + ")");
|
|
203
|
+
//
|
|
204
|
+
// return callback();
|
|
205
|
+
// }
|
|
206
|
+
//
|
|
207
|
+
// if (!alreadyRegistered)
|
|
208
|
+
// {
|
|
209
|
+
// logger.info("New registration - channelId: " + channelId + ",userId=" + user.id + " (" + user.name + ")");
|
|
210
|
+
|
|
211
|
+
//logger.info("Register - channelId: " + channelId + ", userId=" + user.id + " (" + user.name + ")");
|
|
207
212
|
socket.join(channelId);
|
|
208
|
-
}
|
|
213
|
+
//}
|
|
209
214
|
|
|
210
215
|
discover(channelId, function(err, userArray) {
|
|
211
216
|
|
|
212
|
-
if (
|
|
213
|
-
|
|
217
|
+
if (err)
|
|
218
|
+
{
|
|
219
|
+
logger.info("Discover - channelId: " + channelId + ", err: " + JSON.stringify(err));
|
|
220
|
+
}
|
|
221
|
+
else
|
|
222
|
+
{
|
|
223
|
+
//logger.info("Discover - channelId: " + channelId + ", userId=" + user.id + " (" + user.name + ") handing back: " + userArray.length);
|
|
214
224
|
io.sockets.in(channelId).emit("membershipChanged", channelId, userArray);
|
|
215
225
|
}
|
|
216
226
|
|
|
@@ -412,6 +422,8 @@ exports = module.exports = function()
|
|
|
412
422
|
*/
|
|
413
423
|
var register = r.register = function(channelId, user, callback)
|
|
414
424
|
{
|
|
425
|
+
//console.log("Awareness - heard register, channel: " + channelId + ", user: " + user.id);
|
|
426
|
+
|
|
415
427
|
provider.register(channelId, user, callback);
|
|
416
428
|
};
|
|
417
429
|
|
|
@@ -14,28 +14,33 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
14
14
|
{
|
|
15
15
|
super(config);
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
_lock(lockKey, workFunction)
|
|
19
|
+
{
|
|
20
|
+
process.locks.lock(lockKey, workFunction);
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
readOrCreateChannel(channelId, callback) {
|
|
19
24
|
|
|
20
25
|
var self = this;
|
|
21
26
|
|
|
22
27
|
self.readChannel(channelId, function(err, channel) {
|
|
23
|
-
|
|
28
|
+
|
|
24
29
|
if (err) {
|
|
25
30
|
return callback(err);
|
|
26
31
|
}
|
|
27
|
-
|
|
32
|
+
|
|
28
33
|
if (channel) {
|
|
29
34
|
return callback(null, channel);
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
var channel = {};
|
|
33
38
|
self.writeChannel(channelId, channel, function(err) {
|
|
34
|
-
|
|
39
|
+
|
|
35
40
|
if (err) {
|
|
36
41
|
return callback(err);
|
|
37
42
|
}
|
|
38
|
-
|
|
43
|
+
|
|
39
44
|
callback(null, channel);
|
|
40
45
|
});
|
|
41
46
|
});
|
|
@@ -46,26 +51,47 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
46
51
|
register(channelId, user, callback)
|
|
47
52
|
{
|
|
48
53
|
var self = this;
|
|
49
|
-
|
|
54
|
+
|
|
55
|
+
self._lock("channels", function(err, releaseLockFn) {
|
|
56
|
+
self.doRegister(channelId, user, function(err) {
|
|
57
|
+
callback(err);
|
|
58
|
+
return releaseLockFn();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Workhorse method. The "channels" lock is taken out ahead of this being called.
|
|
65
|
+
*
|
|
66
|
+
* @param channelId
|
|
67
|
+
* @param user
|
|
68
|
+
* @param callback
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
doRegister(channelId, user, callback)
|
|
72
|
+
{
|
|
73
|
+
var self = this;
|
|
74
|
+
|
|
50
75
|
self.readOrCreateChannel(channelId, function (err, channel) {
|
|
51
|
-
|
|
76
|
+
|
|
52
77
|
if (err) {
|
|
53
78
|
return callback(err);
|
|
54
79
|
}
|
|
55
|
-
|
|
80
|
+
|
|
56
81
|
if (!channel.users) {
|
|
57
82
|
channel.users = {};
|
|
58
83
|
}
|
|
59
|
-
|
|
84
|
+
|
|
60
85
|
channel.users[user.id] = {
|
|
61
86
|
"user": user,
|
|
62
87
|
"time": new Date().getTime()
|
|
63
88
|
};
|
|
64
|
-
|
|
89
|
+
|
|
65
90
|
self.writeChannel(channelId, channel, function (err) {
|
|
66
91
|
callback(err);
|
|
67
92
|
});
|
|
68
93
|
});
|
|
94
|
+
|
|
69
95
|
}
|
|
70
96
|
|
|
71
97
|
discover(channelId, callback)
|
|
@@ -101,46 +127,86 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
101
127
|
});
|
|
102
128
|
}
|
|
103
129
|
|
|
104
|
-
|
|
130
|
+
checkRegistered(channelId, userId, callback)
|
|
105
131
|
{
|
|
106
132
|
var self = this;
|
|
107
133
|
|
|
108
|
-
self.
|
|
134
|
+
self.readChannel(channelId, function(err, channel) {
|
|
109
135
|
|
|
110
136
|
if (err) {
|
|
111
137
|
return callback(err);
|
|
112
138
|
}
|
|
113
139
|
|
|
140
|
+
if (!channel) {
|
|
141
|
+
return callback(null, false);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!channel.users) {
|
|
145
|
+
return callback(null, false);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (channel.users[userId]) {
|
|
149
|
+
return callback(null, true);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
callback(null, false);
|
|
153
|
+
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
expire(beforeMs, callback)
|
|
158
|
+
{
|
|
159
|
+
var self = this;
|
|
160
|
+
|
|
161
|
+
self._lock("channels", function(err, releaseLockFn) {
|
|
162
|
+
self._expire(beforeMs, function(err) {
|
|
163
|
+
callback(err);
|
|
164
|
+
return releaseLockFn();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @override
|
|
171
|
+
*/
|
|
172
|
+
_expire(beforeMs, callback)
|
|
173
|
+
{
|
|
174
|
+
var self = this;
|
|
175
|
+
|
|
176
|
+
self.listChannelIds(function(err, channelIds) {
|
|
177
|
+
|
|
178
|
+
if (err) {
|
|
179
|
+
return callback(err);
|
|
180
|
+
}
|
|
181
|
+
|
|
114
182
|
if (!channelIds || channelIds.length === 0) {
|
|
115
183
|
return callback(null, [], {});
|
|
116
184
|
}
|
|
117
|
-
|
|
185
|
+
|
|
118
186
|
// a list of channel IDs whose memberships were updated
|
|
119
187
|
var updatedMembershipChannelIds = [];
|
|
120
188
|
var expiredUserIdsByChannelId = {};
|
|
121
|
-
|
|
189
|
+
|
|
122
190
|
var fns = [];
|
|
123
|
-
|
|
191
|
+
|
|
124
192
|
for (var i = 0; i < channelIds.length; i++)
|
|
125
193
|
{
|
|
126
194
|
var channelId = channelIds[i];
|
|
127
|
-
|
|
195
|
+
|
|
128
196
|
var fn = function (channelId, updatedMembershipChannelIds, expiredUserIdsByChannelId, beforeMs) {
|
|
129
197
|
return function (done) {
|
|
130
|
-
|
|
198
|
+
|
|
131
199
|
self.readChannel(channelId, function(err, channel) {
|
|
132
|
-
|
|
200
|
+
|
|
133
201
|
if (err) {
|
|
134
202
|
return done(err);
|
|
135
203
|
}
|
|
136
|
-
|
|
204
|
+
|
|
137
205
|
if (!channel) {
|
|
138
206
|
return done();
|
|
139
207
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (channel.users)
|
|
208
|
+
|
|
209
|
+
if (channel.users && Object.keys(channel.users).length > 0)
|
|
144
210
|
{
|
|
145
211
|
// populate all of the user IDs that need to be removed
|
|
146
212
|
var userIdsToRemove = [];
|
|
@@ -149,75 +215,46 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
149
215
|
var entry = channel.users[userId];
|
|
150
216
|
if (entry.time < beforeMs)
|
|
151
217
|
{
|
|
152
|
-
|
|
218
|
+
updatedMembershipChannelIds.push(channelId);
|
|
153
219
|
userIdsToRemove.push(userId);
|
|
154
|
-
|
|
220
|
+
|
|
155
221
|
var expiredUserIds = expiredUserIdsByChannelId[channelId]
|
|
156
222
|
if (!expiredUserIds) {
|
|
157
223
|
expiredUserIds = expiredUserIdsByChannelId[channelId] = [];
|
|
158
224
|
}
|
|
159
|
-
|
|
225
|
+
|
|
160
226
|
expiredUserIds.push(userId);
|
|
161
227
|
}
|
|
162
228
|
}
|
|
163
|
-
|
|
229
|
+
|
|
164
230
|
// remove the user IDs
|
|
165
231
|
for (var i = 0; i < userIdsToRemove.length; i++)
|
|
166
232
|
{
|
|
167
233
|
delete channel.users[userIdsToRemove[i]];
|
|
168
234
|
}
|
|
235
|
+
|
|
236
|
+
self.writeChannel(channelId, channel, function() {
|
|
237
|
+
done();
|
|
238
|
+
});
|
|
169
239
|
}
|
|
170
|
-
|
|
171
|
-
if (updatedMembership)
|
|
172
|
-
{
|
|
173
|
-
updatedMembershipChannelIds.push(channelId);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
done();
|
|
240
|
+
|
|
177
241
|
});
|
|
178
242
|
};
|
|
179
243
|
}(channelId, updatedMembershipChannelIds, expiredUserIdsByChannelId, beforeMs);
|
|
180
244
|
fns.push(fn);
|
|
181
245
|
}
|
|
182
|
-
|
|
246
|
+
|
|
183
247
|
async.parallel(fns, function(err) {
|
|
184
|
-
|
|
248
|
+
|
|
185
249
|
if (err) {
|
|
186
250
|
return callback(err);
|
|
187
251
|
}
|
|
188
|
-
|
|
252
|
+
|
|
189
253
|
callback(null, updatedMembershipChannelIds, expiredUserIdsByChannelId);
|
|
190
254
|
});
|
|
191
255
|
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
checkRegistered(channelId, userId, callback)
|
|
195
|
-
{
|
|
196
|
-
var self = this;
|
|
197
|
-
|
|
198
|
-
self.readChannel(channelId, function(err, channel) {
|
|
199
|
-
|
|
200
|
-
if (err) {
|
|
201
|
-
return callback(err);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (!channel) {
|
|
205
|
-
return callback(null, false);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (!channel.users) {
|
|
209
|
-
return callback(null, false);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (channel.users[userId]) {
|
|
213
|
-
return callback(null, true);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
callback(null, false);
|
|
217
|
-
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
256
|
+
};
|
|
257
|
+
|
|
221
258
|
acquireLock(channelId, user, callback)
|
|
222
259
|
{
|
|
223
260
|
var self = this;
|
|
@@ -303,14 +340,16 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
303
340
|
callback(null, lock);
|
|
304
341
|
});
|
|
305
342
|
}
|
|
306
|
-
|
|
307
|
-
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
308
347
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
309
348
|
//
|
|
310
349
|
// ABSTRACT METHODS
|
|
311
350
|
//
|
|
312
351
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
313
|
-
|
|
352
|
+
|
|
314
353
|
// ABSTRACT
|
|
315
354
|
readChannel(channelId, callback)
|
|
316
355
|
{
|
|
@@ -328,7 +367,7 @@ class AbstractAsyncProvider extends AbstractProvider
|
|
|
328
367
|
{
|
|
329
368
|
throw new Error("listChannelIds() method is not implemented");
|
|
330
369
|
}
|
|
331
|
-
|
|
370
|
+
|
|
332
371
|
// ABSTRACT
|
|
333
372
|
readLock(lockId, callback)
|
|
334
373
|
{
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Abstract class for an Awareness Provider.
|
|
3
3
|
*
|
|
4
4
|
* This class provides an interface or base functions that any implementation class must implement in order to
|
|
5
|
-
* work with the Awareness Service.
|
|
5
|
+
* work with the Awareness Service.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
class AbstractProvider
|
|
@@ -24,20 +24,6 @@ class MemoryProvider extends AbstractAsyncProvider
|
|
|
24
24
|
callback();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
readOrCreateChannel(channelId, callback)
|
|
28
|
-
{
|
|
29
|
-
var self = this;
|
|
30
|
-
|
|
31
|
-
var channel = self.channelMap[channelId];
|
|
32
|
-
if (channel) {
|
|
33
|
-
return callback(null, channel);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
channel = self.channelMap[channelId] = {};
|
|
37
|
-
|
|
38
|
-
callback(null, channel);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
27
|
readChannel(channelId, callback)
|
|
42
28
|
{
|
|
43
29
|
var self = this;
|