1 | var path = require("path");
|
2 | var async = require("async");
|
3 |
|
4 | /**
|
5 | * Lock Service.
|
6 | *
|
7 | * Provides a method for providing mutex locks so that multiple "threads" in a server (or across cluster, depending on how
|
8 | * this is configured) can coordinate.
|
9 | *
|
10 | * The primary use case is the better orchestration of caching of assets. If one request is attempting to read a node
|
11 | * asset cached to disk and another thread invalidates it, the first thread can get back a 503 or other odd response since
|
12 | * the asset was deleted from disk mid-request.
|
13 | *
|
14 | * The lock service makes it possible for both requests to "sync" around the file path on disk. If request #2 gets the
|
15 | * lock first, the second request will wait until the lock is released before it proceeds to read. The lock would be
|
16 | * released AFTER the asset was completely cleaned up from disk.
|
17 | *
|
18 | * One might argue (and quite well) that returning a 503 or other error code is perfectly fine and that it is really
|
19 | * the front end application's problem to interpret the error and respond (such as by re-requesting the asset). This
|
20 | * may be true but at our goal here is to make things a little cleaner for our customers so that they're either going to
|
21 | * get a 200 or 404. Other HTTP codes may arise but should not be the result of inconsistent state that arises from
|
22 | * lack of coordination among requests.
|
23 | *
|
24 | * @type {*}
|
25 | */
|
26 | exports = module.exports = function()
|
27 | {
|
28 | var provider = null;
|
29 |
|
30 | var r = {};
|
31 |
|
32 | var init = r.init = function(callback)
|
33 | {
|
34 | var self = this;
|
35 |
|
36 | // set up defaults
|
37 | if (!process.env.CLOUDCMS_LOCKS_TYPE) {
|
38 | process.env.CLOUDCMS_LOCKS_TYPE = "memory";
|
39 |
|
40 | if (process.configuration.setup !== "single") {
|
41 | process.env.CLOUDCMS_LOCKS_TYPE = "redis";
|
42 | }
|
43 | }
|
44 |
|
45 | if (!process.configuration.locks) {
|
46 | process.configuration.locks = {};
|
47 | }
|
48 |
|
49 | if (!process.configuration.locks.type) {
|
50 | process.configuration.locks.type = process.env.CLOUDCMS_LOCKS_TYPE;
|
51 | }
|
52 |
|
53 | if (!process.configuration.locks.config) {
|
54 | process.configuration.locks.config = {};
|
55 | }
|
56 |
|
57 | process.env.CLOUDCMS_LOCKS_TYPE = process.configuration.locks.type;
|
58 |
|
59 | var locksConfig = process.configuration.locks.config;
|
60 |
|
61 | provider = require("./providers/" + process.configuration.locks.type)(locksConfig);
|
62 | provider.init(function(err) {
|
63 | callback(err);
|
64 | });
|
65 | };
|
66 |
|
67 | /**
|
68 | * Acquires a lock for a given key.
|
69 | *
|
70 | * @type {Function}
|
71 | */
|
72 | var lock = r.lock = function(key, fn)
|
73 | {
|
74 | provider.lock(key, function(releaseFn) {
|
75 | fn(function(afterReleaseCallback) {
|
76 |
|
77 | releaseFn();
|
78 |
|
79 | if (afterReleaseCallback)
|
80 | {
|
81 | afterReleaseCallback();
|
82 | }
|
83 |
|
84 | });
|
85 | });
|
86 | };
|
87 |
|
88 | return r;
|
89 | }(); |
\ | No newline at end of file |