1 |
|
2 | var CACHE_RETRY_TIMEOUT;
|
3 |
|
4 | CACHE_RETRY_TIMEOUT = 60000;
|
5 |
|
6 | module.exports = function(providerParams, $q) {
|
7 | var $log, Cache, ResourceCacheEntry, ResourceWriteQueue, flushQueueDeferreds, resetDeferred, resolveDeferred;
|
8 | $log = providerParams.$log;
|
9 | ResourceCacheEntry = require('./resource_cache_entry')(providerParams);
|
10 | Cache = require('./cache')(providerParams);
|
11 | flushQueueDeferreds = {};
|
12 | resetDeferred = function(queue) {
|
13 | var deferred;
|
14 | deferred = $q.defer();
|
15 | flushQueueDeferreds[queue.key] = deferred;
|
16 | queue.promise = deferred.promise;
|
17 | return deferred;
|
18 | };
|
19 | resolveDeferred = function(queue) {
|
20 | return flushQueueDeferreds[queue.key].resolve();
|
21 | };
|
22 | return ResourceWriteQueue = (function() {
|
23 | ResourceWriteQueue.prototype.logStatusOfRequest = function(status, action, params, data) {
|
24 | return $log.debug("" + action + " for " + this.key + " " + (angular.toJson(params)) + " " + status + " (queue length: " + this.queue.length + ")", data);
|
25 | };
|
26 |
|
27 | function ResourceWriteQueue(CachedResource, $timeout) {
|
28 | var write, _i, _len, _ref;
|
29 | this.CachedResource = CachedResource;
|
30 | this.$timeout = $timeout;
|
31 | this.key = "" + this.CachedResource.$key + "/write";
|
32 | this.queue = Cache.getItem(this.key, []);
|
33 | _ref = this.queue;
|
34 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
35 | write = _ref[_i];
|
36 | write.busy = false;
|
37 | }
|
38 | resetDeferred(this);
|
39 | if (this.queue.length === 0) {
|
40 | resolveDeferred(this);
|
41 | }
|
42 | }
|
43 |
|
44 | ResourceWriteQueue.prototype.enqueue = function(params, resourceData, action, deferred) {
|
45 | var resourceParams, write, _ref, _ref1;
|
46 | if (this.queue.length === 0) {
|
47 | resetDeferred(this);
|
48 | }
|
49 | resourceParams = angular.isArray(resourceData) ? resourceData.map(function(resource) {
|
50 | return resource.$params();
|
51 | }) : resourceData.$params();
|
52 | write = this.findWrite({
|
53 | params: params,
|
54 | action: action
|
55 | });
|
56 | if (write == null) {
|
57 | this.queue.push({
|
58 | params: params,
|
59 | resourceParams: resourceParams,
|
60 | action: action,
|
61 | deferred: deferred
|
62 | });
|
63 | this._update();
|
64 | } else {
|
65 | if ((_ref = write.deferred) != null) {
|
66 | _ref.promise.then(function(response) {
|
67 | return deferred.resolve(response);
|
68 | });
|
69 | }
|
70 | if ((_ref1 = write.deferred) != null) {
|
71 | _ref1.promise["catch"](function(error) {
|
72 | return deferred.reject(error);
|
73 | });
|
74 | }
|
75 | }
|
76 | return this.logStatusOfRequest('enqueued', action, params, resourceData);
|
77 | };
|
78 |
|
79 | ResourceWriteQueue.prototype.findWrite = function(_arg) {
|
80 | var action, params, write, _i, _len, _ref;
|
81 | action = _arg.action, params = _arg.params;
|
82 | _ref = this.queue;
|
83 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
84 | write = _ref[_i];
|
85 | if (action === write.action && angular.equals(params, write.params)) {
|
86 | return write;
|
87 | }
|
88 | }
|
89 | };
|
90 |
|
91 | ResourceWriteQueue.prototype.removeWrite = function(_arg) {
|
92 | var action, entry, newQueue, params, _i, _len, _ref;
|
93 | action = _arg.action, params = _arg.params;
|
94 | newQueue = [];
|
95 | _ref = this.queue;
|
96 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
97 | entry = _ref[_i];
|
98 | if (!(action === entry.action && angular.equals(params, entry.params))) {
|
99 | newQueue.push(entry);
|
100 | }
|
101 | }
|
102 | this.queue = newQueue;
|
103 | if (this.queue.length === 0 && this.timeoutPromise) {
|
104 | this.$timeout.cancel(this.timeoutPromise);
|
105 | delete this.timeoutPromise;
|
106 | }
|
107 | this._update();
|
108 | if (this.queue.length === 0) {
|
109 | return resolveDeferred(this);
|
110 | }
|
111 | };
|
112 |
|
113 | ResourceWriteQueue.prototype.flush = function(done) {
|
114 | var write, _i, _len, _ref, _results;
|
115 | if (angular.isFunction(done)) {
|
116 | this.promise.then(done);
|
117 | }
|
118 | this._setFlushTimeout();
|
119 | _ref = this.queue;
|
120 | _results = [];
|
121 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
122 | write = _ref[_i];
|
123 | _results.push(this._processWrite(write));
|
124 | }
|
125 | return _results;
|
126 | };
|
127 |
|
128 | ResourceWriteQueue.prototype.processResource = function(params, done) {
|
129 | var notDone, write, _i, _len, _ref, _results;
|
130 | notDone = true;
|
131 | _ref = this._writesForResource(params);
|
132 | _results = [];
|
133 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
134 | write = _ref[_i];
|
135 | _results.push(this._processWrite(write, (function(_this) {
|
136 | return function() {
|
137 | if (notDone && _this._writesForResource(params).length === 0) {
|
138 | notDone = false;
|
139 | return done();
|
140 | }
|
141 | };
|
142 | })(this)));
|
143 | }
|
144 | return _results;
|
145 | };
|
146 |
|
147 | ResourceWriteQueue.prototype._writesForResource = function(params) {
|
148 | var write, _i, _len, _ref, _results;
|
149 | _ref = this.queue;
|
150 | _results = [];
|
151 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
152 | write = _ref[_i];
|
153 | if (angular.equals(params, write.params)) {
|
154 | _results.push(write);
|
155 | }
|
156 | }
|
157 | return _results;
|
158 | };
|
159 |
|
160 | ResourceWriteQueue.prototype._processWrite = function(write, done) {
|
161 | var cacheEntries, onFailure, onSuccess, writeData;
|
162 | if (write.busy) {
|
163 | return;
|
164 | }
|
165 | write.busy = true;
|
166 | if (angular.isArray(write.resourceParams)) {
|
167 | cacheEntries = write.resourceParams.map((function(_this) {
|
168 | return function(resourceParams) {
|
169 | return new ResourceCacheEntry(_this.CachedResource.$key, resourceParams).load();
|
170 | };
|
171 | })(this));
|
172 | writeData = cacheEntries.map(function(cacheEntry) {
|
173 | return cacheEntry.value;
|
174 | });
|
175 | } else {
|
176 | cacheEntries = [new ResourceCacheEntry(this.CachedResource.$key, write.resourceParams).load()];
|
177 | writeData = cacheEntries[0].value;
|
178 | }
|
179 | onSuccess = (function(_this) {
|
180 | return function(value) {
|
181 | var _ref;
|
182 | _this.removeWrite(write);
|
183 | if ((_ref = write.deferred) != null) {
|
184 | _ref.resolve(value);
|
185 | }
|
186 | _this.logStatusOfRequest('succeeded', write.action, write.resourceParams, writeData);
|
187 | if (angular.isFunction(done)) {
|
188 | return done();
|
189 | }
|
190 | };
|
191 | })(this);
|
192 | onFailure = (function(_this) {
|
193 | return function(error) {
|
194 | var _ref;
|
195 | if (error && error.status >= 400 && error.status < 500) {
|
196 | _this.removeWrite(write);
|
197 | $log.error("" + write.action + " to " + _this.CachedResource.$key + " failed with error " + error.status, {
|
198 | method: error.config.method,
|
199 | url: error.config.url,
|
200 | writeData: writeData
|
201 | });
|
202 | } else {
|
203 | write.busy = false;
|
204 | _this.logStatusOfRequest("failed with error " + (angular.toJson(error)) + "; still in queue", write.action, write.resourceParams, writeData);
|
205 | }
|
206 | return (_ref = write.deferred) != null ? _ref.reject(error) : void 0;
|
207 | };
|
208 | })(this);
|
209 | this.CachedResource.$resource[write.action](write.params, writeData, onSuccess, onFailure).$promise.then((function(_this) {
|
210 | return function(savedResources) {
|
211 | var cacheEntry, resource, resourceInstance, _i, _len, _results;
|
212 | savedResources = angular.isArray(savedResources) ? savedResources : [savedResources];
|
213 | _results = [];
|
214 | for (_i = 0, _len = savedResources.length; _i < _len; _i++) {
|
215 | resource = savedResources[_i];
|
216 | resourceInstance = new _this.CachedResource(resource);
|
217 | cacheEntry = new ResourceCacheEntry(_this.CachedResource.$key, resourceInstance.$params()).load();
|
218 | _results.push(cacheEntry.set(resource, false));
|
219 | }
|
220 | return _results;
|
221 | };
|
222 | })(this));
|
223 | return this.logStatusOfRequest('processed', write.action, write.resourceParams, writeData);
|
224 | };
|
225 |
|
226 | ResourceWriteQueue.prototype._setFlushTimeout = function() {
|
227 | if (this.queue.length > 0 && !this.timeoutPromise) {
|
228 | this.timeoutPromise = this.$timeout(angular.bind(this, this.flush), CACHE_RETRY_TIMEOUT);
|
229 | return this.timeoutPromise.then((function(_this) {
|
230 | return function() {
|
231 | delete _this.timeoutPromise;
|
232 | return _this._setFlushTimeout();
|
233 | };
|
234 | })(this));
|
235 | }
|
236 | };
|
237 |
|
238 | ResourceWriteQueue.prototype._update = function() {
|
239 | var savableQueue;
|
240 | savableQueue = this.queue.map(function(write) {
|
241 | return {
|
242 | params: write.params,
|
243 | resourceParams: write.resourceParams,
|
244 | action: write.action
|
245 | };
|
246 | });
|
247 | return Cache.setItem(this.key, savableQueue);
|
248 | };
|
249 |
|
250 | return ResourceWriteQueue;
|
251 |
|
252 | })();
|
253 | };
|