cloudcms-server 3.3.1-beta.8 → 4.0.0-beta.1
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/LICENSE +1 -1
- package/README.md +1 -1
- package/broadcast/broadcast.js +6 -3
- package/broadcast/providers/redis.js +24 -49
- package/clients/nrp.js +117 -0
- package/clients/redis.js +64 -0
- package/d1/index.js +629 -0
- package/d1/index.js.works +203 -0
- package/d1/package.json +86 -0
- package/d1/package.json.works +14 -0
- package/duster/helpers/sample/nyt.js +2 -1
- package/framework/controllers.js +4 -4
- package/index.js +26 -14
- package/insight/insight.js +1 -1
- package/launchpad/index.js +203 -11
- package/launchpad/launchers/cluster.js +103 -110
- package/launchpad/launchers/redis.js +70 -0
- package/launchpad/launchers/single.js +36 -22
- package/locks/locks.js +63 -9
- package/locks/providers/cluster.js +3 -1
- package/locks/providers/memory.js +10 -7
- package/locks/providers/redis.js +62 -82
- package/middleware/admin/admin.js +3 -3
- package/middleware/authentication/adapters/session.js +11 -8
- package/middleware/authentication/authentication.js +28 -16
- package/middleware/authentication/authenticators/default.js +5 -2
- package/middleware/authentication/authenticators/session.js +5 -2
- package/middleware/authentication/providers/saml.js +1 -1
- package/middleware/authorization/authorization.js +11 -8
- package/middleware/awareness/awareness.js +55 -31
- package/middleware/awareness/plugins/editorial.js +4 -4
- package/middleware/awareness/providers/abstract-async.js +107 -84
- package/middleware/awareness/providers/abstract.js +1 -1
- package/middleware/awareness/providers/memory.js +0 -14
- package/middleware/awareness/providers/redis.js +186 -279
- package/middleware/cache/cache.js +4 -2
- package/middleware/cache/providers/redis.js +127 -89
- package/middleware/cache/providers/shared-memory.js +3 -3
- package/middleware/cloudcms/cloudcms.js +22 -16
- package/middleware/form/form.js +3 -3
- package/middleware/modules/modules.js +63 -10
- package/middleware/proxy/proxy.js +8 -21
- package/middleware/stores/stores.js +48 -5
- package/middleware/themes/themes.js +49 -0
- package/middleware/virtual-config/virtual-config.js +11 -8
- package/middleware/wcm/wcm.js +4 -4
- package/notifications/notifications.js +27 -4
- package/package.json +30 -25
- package/server/index.js +508 -412
- package/server/standalone.js +9 -0
- package/temp/clusterlock/index.js +3 -3
- package/temp/clusterlock/package.json +1 -1
- package/temp/passport-saml/LICENSE +23 -0
- package/temp/passport-saml/README.md +406 -0
- package/temp/passport-saml/lib/node-saml/algorithms.d.ts +5 -0
- package/temp/passport-saml/lib/node-saml/algorithms.js +41 -0
- package/temp/passport-saml/lib/node-saml/algorithms.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/index.d.ts +3 -0
- package/temp/passport-saml/lib/node-saml/index.js +6 -0
- package/temp/passport-saml/lib/node-saml/index.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/inmemory-cache-provider.d.ts +45 -0
- package/temp/passport-saml/lib/node-saml/inmemory-cache-provider.js +86 -0
- package/temp/passport-saml/lib/node-saml/inmemory-cache-provider.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/saml-post-signing.d.ts +3 -0
- package/temp/passport-saml/lib/node-saml/saml-post-signing.js +15 -0
- package/temp/passport-saml/lib/node-saml/saml-post-signing.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/saml.d.ts +77 -0
- package/temp/passport-saml/lib/node-saml/saml.js +1170 -0
- package/temp/passport-saml/lib/node-saml/saml.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/types.d.ts +95 -0
- package/temp/passport-saml/lib/node-saml/types.js +8 -0
- package/temp/passport-saml/lib/node-saml/types.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/utility.d.ts +3 -0
- package/temp/passport-saml/lib/node-saml/utility.js +19 -0
- package/temp/passport-saml/lib/node-saml/utility.js.map +1 -0
- package/temp/passport-saml/lib/node-saml/xml.d.ts +21 -0
- package/temp/passport-saml/lib/node-saml/xml.js +140 -0
- package/temp/passport-saml/lib/node-saml/xml.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/index.d.ts +6 -0
- package/temp/passport-saml/lib/passport-saml/index.js +11 -0
- package/temp/passport-saml/lib/passport-saml/index.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/multiSamlStrategy.d.ts +13 -0
- package/temp/passport-saml/lib/passport-saml/multiSamlStrategy.js +63 -0
- package/temp/passport-saml/lib/passport-saml/multiSamlStrategy.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/strategy.d.ts +20 -0
- package/temp/passport-saml/lib/passport-saml/strategy.js +167 -0
- package/temp/passport-saml/lib/passport-saml/strategy.js.map +1 -0
- package/temp/passport-saml/lib/passport-saml/types.d.ts +51 -0
- package/temp/passport-saml/lib/passport-saml/types.js +11 -0
- package/temp/passport-saml/lib/passport-saml/types.js.map +1 -0
- package/temp/passport-saml/package.json +96 -0
- package/util/auth.js +6 -6
- package/util/cloudcms.js +85 -88
- package/util/proxy-factory.js +159 -268
- package/util/redis.js +113 -0
- package/util/renditions.js +12 -6
- package/util/request.js +48 -12
- package/util/util.js +16 -2
- package/launchpad/launchers/sticky-cluster.js +0 -43
- package/temp/memored/.jshintrc +0 -4
- package/temp/memored/README.md +0 -240
- package/temp/memored/demo/demo1.js +0 -37
- package/temp/memored/demo/demo2.js +0 -32
- package/temp/memored/gulpfile.js +0 -8
- package/temp/memored/index.js +0 -343
- package/temp/memored/package.json +0 -54
- package/temp/memored/spec/memored.spec.js +0 -265
- package/web/cms/ice.js +0 -109
- package/web/cms/preview.js +0 -106
|
@@ -1,121 +1,114 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var cpuCount = require("os").cpus().length;
|
|
12
|
-
|
|
13
|
-
var factoryCallback = options.factory;
|
|
14
|
-
var reportCallback = options.report;
|
|
15
|
-
if (!reportCallback) {
|
|
16
|
-
reportCallback = function() { };
|
|
17
|
-
}
|
|
18
|
-
var completionCallback = options.complete;
|
|
19
|
-
if (!completionCallback) {
|
|
20
|
-
completionCallback = function() { };
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (cluster.isMaster)
|
|
1
|
+
const cluster = require("cluster");
|
|
2
|
+
const { Server } = require("socket.io");
|
|
3
|
+
const { setupMaster, setupWorker } = require("@socket.io/sticky");
|
|
4
|
+
const { createAdapter, setupPrimary } = require("@socket.io/cluster-adapter");
|
|
5
|
+
|
|
6
|
+
module.exports = function(config) {
|
|
7
|
+
|
|
8
|
+
var r = {};
|
|
9
|
+
|
|
10
|
+
r.startCluster = function(httpServer, callback)
|
|
24
11
|
{
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
var fn = function (i, workers) {
|
|
31
|
-
return function (done) {
|
|
32
|
-
|
|
33
|
-
var spawn = function (i, afterSpawnFn) {
|
|
34
|
-
|
|
35
|
-
if (!afterSpawnFn) {
|
|
36
|
-
afterSpawnFn = function () { };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
workers[i] = cluster.fork();
|
|
40
|
-
|
|
41
|
-
workers[i].on('exit', function (worker, workers, i) {
|
|
42
|
-
return function() {
|
|
43
|
-
console.error("launchpad: worker " + i + " exited");
|
|
44
|
-
worker.exited = true;
|
|
45
|
-
|
|
46
|
-
// are all workers exited?
|
|
47
|
-
var all = true;
|
|
48
|
-
for (var z = 0; z < workers.length; z++)
|
|
49
|
-
{
|
|
50
|
-
if (!workers[z].exited) {
|
|
51
|
-
all = false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (all)
|
|
56
|
-
{
|
|
57
|
-
console.log("launchpad: all workers exited, terminating process");
|
|
58
|
-
return process.exit(-1);
|
|
59
|
-
}
|
|
12
|
+
// setup sticky sessions
|
|
13
|
+
setupMaster(httpServer, {
|
|
14
|
+
//loadBalancingMethod: "least-connection"
|
|
15
|
+
loadBalancingMethod: "round-robin"
|
|
16
|
+
});
|
|
60
17
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.log("launchpad: restarting worker: " + i);
|
|
64
|
-
spawn(i);
|
|
65
|
-
worker.exited = false;
|
|
66
|
-
}, 5000);
|
|
67
|
-
}
|
|
68
|
-
}(workers[i], workers, i));
|
|
18
|
+
// setup connections between the workers
|
|
19
|
+
setupPrimary();
|
|
69
20
|
|
|
70
|
-
|
|
21
|
+
// needed for packets containing buffers
|
|
22
|
+
// cluster.setupPrimary({
|
|
23
|
+
// serialization: "advanced"
|
|
24
|
+
// });
|
|
71
25
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}(i, workers);
|
|
83
|
-
fns.push(fn);
|
|
26
|
+
return callback();
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
r.afterStartCluster = function(httpServer, callback)
|
|
30
|
+
{
|
|
31
|
+
var startupCount = 0;
|
|
32
|
+
|
|
33
|
+
var numCPUs = require("os").cpus().length;
|
|
34
|
+
if (process.env.FORCE_SINGLE_CPU) {
|
|
35
|
+
numCPUs = 1;
|
|
84
36
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (workers.length > 0)
|
|
93
|
-
{
|
|
94
|
-
workers[0].send("server-report");
|
|
37
|
+
|
|
38
|
+
var workers = [];
|
|
39
|
+
for (let i = 0; i < numCPUs; i++)
|
|
40
|
+
{
|
|
41
|
+
var workerEnv = {};
|
|
42
|
+
if (i === 0) {
|
|
43
|
+
workerEnv["CLUSTER_REPORT"] = true;
|
|
95
44
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
45
|
+
|
|
46
|
+
var worker = cluster.fork(workerEnv);
|
|
47
|
+
|
|
48
|
+
worker.on('message', function (msg, c) {
|
|
49
|
+
//console.log("Worker message: " + msg + ", c: " + c);
|
|
50
|
+
if (msg === "worker-startup") {
|
|
51
|
+
startupCount++;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
worker.on('error', function(err) {
|
|
56
|
+
console.log("Worker.on(error) - " + JSON.stringify(err));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
workers.push(worker);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
cluster.on("error", function(err) {
|
|
63
|
+
console.log("Cluster.on(error) - " + JSON.stringify(err));
|
|
100
64
|
});
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
65
|
+
|
|
66
|
+
cluster.on("exit", (worker) => {
|
|
67
|
+
console.log(`Worker ${worker.process.pid} died`);
|
|
68
|
+
//cluster.fork();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// wait for workers to start
|
|
72
|
+
var waitFn = function() {
|
|
73
|
+
setTimeout(function() {
|
|
74
|
+
if (startupCount >= numCPUs) {
|
|
75
|
+
return callback(null, workers);
|
|
76
|
+
}
|
|
77
|
+
else
|
|
114
78
|
{
|
|
115
|
-
|
|
79
|
+
waitFn();
|
|
116
80
|
}
|
|
117
|
-
|
|
81
|
+
}, 25);
|
|
82
|
+
};
|
|
83
|
+
waitFn();
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
r.afterStartServer = function(app, httpServer, callback)
|
|
87
|
+
{
|
|
88
|
+
// worker
|
|
89
|
+
|
|
90
|
+
const io = new Server(httpServer);
|
|
91
|
+
httpServer.io = io;
|
|
92
|
+
|
|
93
|
+
// use the cluster adapter
|
|
94
|
+
io.adapter(createAdapter());
|
|
95
|
+
|
|
96
|
+
// setup connection with the primary process
|
|
97
|
+
setupWorker(io);
|
|
98
|
+
|
|
99
|
+
// on connect
|
|
100
|
+
io.on("connection", (socket) => {
|
|
101
|
+
// TODO
|
|
102
|
+
|
|
103
|
+
// always catch err
|
|
104
|
+
socket.on("error", function(err) {
|
|
105
|
+
console.log("Caught socket error");
|
|
106
|
+
console.log(err.stack);
|
|
118
107
|
});
|
|
119
108
|
});
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
|
|
110
|
+
return callback();
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return r;
|
|
114
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const { Server } = require("socket.io");
|
|
2
|
+
const { setupWorker } = require("@socket.io/sticky");
|
|
3
|
+
const { createAdapter } = require("@socket.io/redis-adapter");
|
|
4
|
+
const redisHelper = require("../../util/redis");
|
|
5
|
+
const IORedis = require("ioredis");
|
|
6
|
+
|
|
7
|
+
const clusterLauncherFactory = require("./cluster");
|
|
8
|
+
|
|
9
|
+
module.exports = function(config) {
|
|
10
|
+
|
|
11
|
+
var clusterLauncher = clusterLauncherFactory(config);
|
|
12
|
+
|
|
13
|
+
var r = {};
|
|
14
|
+
|
|
15
|
+
r.startCluster = function(httpServer, callback)
|
|
16
|
+
{
|
|
17
|
+
clusterLauncher.startCluster(httpServer, callback);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
r.afterStartCluster = function(httpServer, callback)
|
|
21
|
+
{
|
|
22
|
+
clusterLauncher.afterStartCluster(httpServer, callback);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
r.afterStartServer = function(app, httpServer, callback)
|
|
26
|
+
{
|
|
27
|
+
var redisOptions = redisHelper.redisOptions({}, "CLOUDCMS_CLUSTER");
|
|
28
|
+
var pubClient = new IORedis(redisOptions.url);
|
|
29
|
+
var subClient = pubClient.duplicate();
|
|
30
|
+
|
|
31
|
+
const io = new Server(httpServer);
|
|
32
|
+
httpServer.io = io;
|
|
33
|
+
|
|
34
|
+
io.engine.on("connection_error", function(err) {
|
|
35
|
+
// console.log("CONNECTION ERROR");
|
|
36
|
+
// console.log("REQUEST: ", err.req); // the request object
|
|
37
|
+
// console.log("CODE: " + err.code); // the error code, for example 1
|
|
38
|
+
// console.log("MESSAGE: ", err.message); // the error message, for example "Session ID unknown"
|
|
39
|
+
// console.log("CONTEXT: ", err.context); // some additional error context
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// use the redis adapter
|
|
43
|
+
io.adapter(createAdapter(pubClient, subClient, {
|
|
44
|
+
//publishOnSpecificResponseChannel: true
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
// setup connection with the primary process
|
|
48
|
+
setupWorker(io);
|
|
49
|
+
|
|
50
|
+
// on connect
|
|
51
|
+
io.on("connection", (socket) => {
|
|
52
|
+
//console.log("Redis Launcher on('connection') - socket id:" + socket.id);
|
|
53
|
+
socket.on('message', function(m) {
|
|
54
|
+
console.log("Socket Connection message: " + m);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// always catch err
|
|
58
|
+
socket.on("error", function(err) {
|
|
59
|
+
console.log("Caught socket error");
|
|
60
|
+
console.log(err.stack);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// TODO
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return callback();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return r;
|
|
70
|
+
}
|
|
@@ -1,23 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
const { Server } = require("socket.io");
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
3
|
+
module.exports = function(config) {
|
|
4
|
+
|
|
5
|
+
var r = {};
|
|
6
|
+
|
|
7
|
+
r.startCluster = function(httpServer, callback)
|
|
8
|
+
{
|
|
9
|
+
callback();
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
r.afterStartCluster = function(httpServer, callback)
|
|
13
|
+
{
|
|
14
|
+
callback();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
r.afterStartServer = function(app, httpServer, callback)
|
|
18
|
+
{
|
|
19
|
+
var io = new Server(httpServer);
|
|
20
|
+
|
|
21
|
+
io.on("connection", (socket) => {
|
|
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
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
httpServer.io = io;
|
|
32
|
+
|
|
33
|
+
callback();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return r;
|
|
37
|
+
}
|
package/locks/locks.js
CHANGED
|
@@ -25,6 +25,8 @@ var async = require("async");
|
|
|
25
25
|
*/
|
|
26
26
|
exports = module.exports = function()
|
|
27
27
|
{
|
|
28
|
+
var lockTimeoutMs = 120000; // two minutes
|
|
29
|
+
|
|
28
30
|
var provider = null;
|
|
29
31
|
|
|
30
32
|
var r = {};
|
|
@@ -34,10 +36,13 @@ exports = module.exports = function()
|
|
|
34
36
|
var self = this;
|
|
35
37
|
|
|
36
38
|
// set up defaults
|
|
37
|
-
if (!process.env.CLOUDCMS_LOCKS_TYPE)
|
|
39
|
+
if (!process.env.CLOUDCMS_LOCKS_TYPE)
|
|
40
|
+
{
|
|
38
41
|
process.env.CLOUDCMS_LOCKS_TYPE = "memory";
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
|
|
43
|
+
// auto-configure
|
|
44
|
+
if (process.env.CLOUDCMS_LAUNCHPAD_SETUP === "redis")
|
|
45
|
+
{
|
|
41
46
|
process.env.CLOUDCMS_LOCKS_TYPE = "redis";
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -71,12 +76,61 @@ exports = module.exports = function()
|
|
|
71
76
|
*/
|
|
72
77
|
var lock = r.lock = function(key, fn)
|
|
73
78
|
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
var __log = function(key, text) {
|
|
80
|
+
// var skip = false;
|
|
81
|
+
// if (key === "channels") { skip = true; }
|
|
82
|
+
// if (!skip) {
|
|
83
|
+
// console.log("[LOCK: " + key + "] " + text);
|
|
84
|
+
// }
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
__log(key, "request");
|
|
88
|
+
provider.lock(key, function(err, _releaseFn) {
|
|
89
|
+
|
|
90
|
+
if (err) {
|
|
91
|
+
console.log("[LOCK: " + key + "] err: ", err);
|
|
92
|
+
try { _releaseFn(); } catch (e) { }
|
|
93
|
+
return fn(err);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// wrap the releaseFn with a wrapper that can only fire once
|
|
97
|
+
var releaseFn = function(_releaseFn)
|
|
98
|
+
{
|
|
99
|
+
var triggered = false;
|
|
100
|
+
return function() {
|
|
101
|
+
if (!triggered) {
|
|
102
|
+
triggered = true;
|
|
103
|
+
_releaseFn();
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}(_releaseFn);
|
|
110
|
+
|
|
111
|
+
// after 120 seconds, we force release lock (if it hasn't already been released)
|
|
112
|
+
(function(key, releaseFn) {
|
|
113
|
+
setTimeout(function() {
|
|
114
|
+
var released = releaseFn();
|
|
115
|
+
if (released) {
|
|
116
|
+
__log(key, "timed out, released");
|
|
117
|
+
}
|
|
118
|
+
}, lockTimeoutMs);
|
|
119
|
+
})(key, releaseFn);
|
|
120
|
+
|
|
121
|
+
__log(key, "taken");
|
|
122
|
+
|
|
123
|
+
fn(err, function(afterReleaseCallback) {
|
|
124
|
+
__log(key, "pre-release");
|
|
125
|
+
|
|
126
|
+
var released = releaseFn();
|
|
127
|
+
if (released) {
|
|
128
|
+
__log(key, "released");
|
|
129
|
+
} else {
|
|
130
|
+
__log(key, "not released, was previously released on timeout");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (released && afterReleaseCallback)
|
|
80
134
|
{
|
|
81
135
|
afterReleaseCallback();
|
|
82
136
|
}
|
|
@@ -13,13 +13,15 @@ exports = module.exports = function(lockConfig)
|
|
|
13
13
|
|
|
14
14
|
r.init = function(callback)
|
|
15
15
|
{
|
|
16
|
+
ClusterLock.setup();
|
|
17
|
+
|
|
16
18
|
callback();
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
r.lock = function(key, fn)
|
|
20
22
|
{
|
|
21
23
|
ClusterLock.lock(key, function(releaseCallbackFn) {
|
|
22
|
-
fn(releaseCallbackFn);
|
|
24
|
+
fn(null, releaseCallbackFn);
|
|
23
25
|
});
|
|
24
26
|
};
|
|
25
27
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
var ReadWriteLock = require("rwlock");
|
|
1
|
+
var AsyncLock = require('async-lock');
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Simple in-memory lock service.
|
|
@@ -12,8 +10,8 @@ var ReadWriteLock = require("rwlock");
|
|
|
12
10
|
exports = module.exports = function(lockConfig)
|
|
13
11
|
{
|
|
14
12
|
var r = {};
|
|
15
|
-
|
|
16
|
-
var
|
|
13
|
+
|
|
14
|
+
var lock = new AsyncLock();
|
|
17
15
|
|
|
18
16
|
r.init = function(callback)
|
|
19
17
|
{
|
|
@@ -22,8 +20,13 @@ exports = module.exports = function(lockConfig)
|
|
|
22
20
|
|
|
23
21
|
r.lock = function(key, fn)
|
|
24
22
|
{
|
|
25
|
-
|
|
26
|
-
fn(releaseCallbackFn);
|
|
23
|
+
lock.acquire(key, function(releaseCallbackFn) {
|
|
24
|
+
fn(null, releaseCallbackFn);
|
|
25
|
+
}, function(err, ret) {
|
|
26
|
+
// lock was released
|
|
27
|
+
if (err) {
|
|
28
|
+
console.error("Memory Lock heard error: ", err, " return value: ", ret);
|
|
29
|
+
}
|
|
27
30
|
});
|
|
28
31
|
};
|
|
29
32
|
|
package/locks/providers/redis.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const redisHelper = require("../../util/redis");
|
|
2
|
+
|
|
3
|
+
const IORedis = require("ioredis");
|
|
4
|
+
var Redlock = require("redlock");
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Redis lock service.
|
|
@@ -9,98 +10,77 @@ var logFactory = require("../../util/logger");
|
|
|
9
10
|
*/
|
|
10
11
|
exports = module.exports = function(locksConfig)
|
|
11
12
|
{
|
|
12
|
-
var
|
|
13
|
-
redisLock.setDefaults({
|
|
14
|
-
timeout: 200000,
|
|
15
|
-
retries: 2000,
|
|
16
|
-
delay: 50
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
var nrp = null;
|
|
13
|
+
var redlock = null;
|
|
20
14
|
var client = null;
|
|
21
|
-
|
|
22
|
-
var logger =
|
|
23
|
-
|
|
24
|
-
// allow for global redis default
|
|
25
|
-
// allow for redis broadcast specific
|
|
26
|
-
// otherwise default to error
|
|
27
|
-
if (typeof(process.env.CLOUDCMS_REDIS_DEBUG_LEVEL) !== "undefined") {
|
|
28
|
-
logger.setLevel(("" + process.env.CLOUDCMS_REDIS_DEBUG_LEVEL).toLowerCase(), true);
|
|
29
|
-
}
|
|
30
|
-
else if (typeof(process.env.CLOUDCMS_LOCKS_REDIS_DEBUG_LEVEL) !== "undefined") {
|
|
31
|
-
logger.setLevel(("" + process.env.CLOUDCMS_LOCKS_REDIS_DEBUG_LEVEL).toLowerCase(), true);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
logger.setLevel("error");
|
|
35
|
-
}
|
|
36
|
-
|
|
15
|
+
|
|
16
|
+
var logger = redisHelper.redisLogger("REDIS_LOCKS", "CLOUDCMS_LOCKS_", "debug")
|
|
17
|
+
|
|
37
18
|
var r = {};
|
|
38
19
|
|
|
39
20
|
r.init = function(callback)
|
|
40
21
|
{
|
|
41
|
-
var
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
client = redis.createClient(redisPort, redisEndpoint, redisOptions);
|
|
22
|
+
var redisOptions = redisHelper.redisOptions(locksConfig);
|
|
23
|
+
client = new IORedis(redisOptions.url);
|
|
24
|
+
|
|
25
|
+
redlock = new Redlock(
|
|
26
|
+
[client],
|
|
27
|
+
{
|
|
28
|
+
// the expected clock drift; for more details
|
|
29
|
+
// see http://redis.io/topics/distlock
|
|
30
|
+
driftFactor: 0.01, // multiplied by lock ttl to determine drift time
|
|
31
|
+
|
|
32
|
+
// the max number of times Redlock will attempt
|
|
33
|
+
// to lock a resource before erroring
|
|
34
|
+
retryCount: 10,
|
|
35
|
+
|
|
36
|
+
// the time in ms between attempts
|
|
37
|
+
retryDelay: 200, // time in ms
|
|
38
|
+
|
|
39
|
+
// the max time in ms randomly added to retries
|
|
40
|
+
// to improve performance under high contention
|
|
41
|
+
// see https://www.awsarchitectureblog.com/2015/03/backoff.html
|
|
42
|
+
retryJitter: 200 // time in ms
|
|
43
|
+
}
|
|
44
|
+
);
|
|
66
45
|
|
|
67
|
-
callback();
|
|
46
|
+
return callback();
|
|
68
47
|
};
|
|
69
48
|
|
|
70
49
|
r.lock = function(key, fn)
|
|
71
50
|
{
|
|
51
|
+
key = key.trim();
|
|
52
|
+
key = key.toLowerCase();
|
|
53
|
+
key = key.replace(/[\W_]+/g,"");
|
|
54
|
+
|
|
72
55
|
var lockKey = "cloudcms:locks:write:" + key;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
logger.info("lock.release - " + lockKey);
|
|
79
|
-
lock.release(function(err) {
|
|
80
|
-
|
|
81
|
-
if (err) {
|
|
82
|
-
console.log("Failed to release redis lock: " + lockKey);
|
|
83
|
-
console.log("Error: " + err);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
logger.info("lock.released - " + lockKey);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}(lock, lockKey);
|
|
91
|
-
|
|
92
|
-
logger.info("lock.acquire - " + lockKey);
|
|
93
|
-
lock.acquire(lockKey, function(err) {
|
|
94
|
-
|
|
56
|
+
|
|
57
|
+
logger.debug("lock.acquire:", lockKey);
|
|
58
|
+
|
|
59
|
+
redlock.lock(lockKey, 2000, function(err, lock) {
|
|
60
|
+
|
|
95
61
|
if (err) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return;
|
|
62
|
+
logger.error("Failed to acquire redis lock:", lockKey, err);
|
|
63
|
+
return fn(err);
|
|
99
64
|
}
|
|
100
|
-
|
|
101
|
-
logger.
|
|
102
|
-
|
|
103
|
-
|
|
65
|
+
|
|
66
|
+
logger.debug("lock.acquired:", lockKey);
|
|
67
|
+
|
|
68
|
+
var releaseCallbackFn = function(lock, lockKey) {
|
|
69
|
+
return function() {
|
|
70
|
+
|
|
71
|
+
logger.debug("lock.release:", lockKey);
|
|
72
|
+
|
|
73
|
+
lock.unlock(function(err) {
|
|
74
|
+
if (err) {
|
|
75
|
+
logger.error("Failed to release redis lock:", lockKey, err);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}(lock, lockKey);
|
|
80
|
+
|
|
81
|
+
logger.debug("lock.invokeFn");
|
|
82
|
+
fn(null, releaseCallbackFn);
|
|
83
|
+
|
|
104
84
|
});
|
|
105
85
|
};
|
|
106
86
|
|