Skip to content

Commit e35531d

Browse files
IgorMinarvojtajina
authored andcommitted
feat($cacheFactory): add general purpose $cacheFactory service
1 parent 0006fe3 commit e35531d

File tree

8 files changed

+482
-0
lines changed

8 files changed

+482
-0
lines changed

Rakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ANGULAR = [
1616
'src/filters.js',
1717
'src/formatters.js',
1818
'src/validators.js',
19+
'src/service/cacheFactory.js',
1920
'src/service/cookieStore.js',
2021
'src/service/cookies.js',
2122
'src/service/defer.js',

jsTestDriver-coverage.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ load:
1919
- src/filters.js
2020
- src/formatters.js
2121
- src/validators.js
22+
- src/service/cacheFactory.js
2223
- src/service/cookieStore.js
2324
- src/service/cookies.js
2425
- src/service/defer.js

jsTestDriver-jquery.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ load:
1919
- src/filters.js
2020
- src/formatters.js
2121
- src/validators.js
22+
- src/service/cacheFactory.js
2223
- src/service/cookieStore.js
2324
- src/service/cookies.js
2425
- src/service/defer.js

jsTestDriver-perf.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ load:
1717
- src/filters.js
1818
- src/formatters.js
1919
- src/validators.js
20+
- src/service/cacheFactory.js
2021
- src/service/cookieStore.js
2122
- src/service/cookies.js
2223
- src/service/defer.js

jsTestDriver.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ load:
1919
- src/filters.js
2020
- src/formatters.js
2121
- src/validators.js
22+
- src/service/cacheFactory.js
2223
- src/service/cookieStore.js
2324
- src/service/cookies.js
2425
- src/service/defer.js

src/angular-bootstrap.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103

104104
// Extension points
105105

106+
'service/cacheFactory.js',
106107
'service/cookieStore.js',
107108
'service/cookies.js',
108109
'service/defer.js',

src/service/cacheFactory.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/**
2+
* @workInProgress
3+
* @ngdoc service
4+
* @name angular.service.$cacheFactory
5+
*
6+
* @description
7+
* Factory that constructs cache objects.
8+
*
9+
*
10+
* @param {string} cacheId Name or id of the newly created cache.
11+
* @param {object=} options Options object that specifies the cache behavior. Properties:
12+
*
13+
* - `{number=}` `capacity` — turns the cache into LRU cache.
14+
*
15+
* @returns {object} Newly created cache object with the following set of methods:
16+
*
17+
* - `{string}` `id()` — Returns id or name of the cache.
18+
* - `{number}` `size()` — Returns number of items currently in the cache
19+
* - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache
20+
* - `{(*}} `get({string} key) — Returns cached value for `key` or undefined for cache miss.
21+
* - `{void}` `remove{string} key) — Removes a key-value pair from the cache.
22+
* - `{void}` `removeAll() — Removes all cached values.
23+
*
24+
*/
25+
angularServiceInject('$cacheFactory', function() {
26+
27+
var caches = {};
28+
29+
function cacheFactory(cacheId, options) {
30+
if (cacheId in caches) {
31+
throw Error('cacheId ' + cacheId + ' taken');
32+
}
33+
34+
var size = 0,
35+
stats = extend({}, options, {id: cacheId}),
36+
data = {},
37+
capacity = (options && options.capacity) || Number.MAX_VALUE,
38+
lruHash = {},
39+
freshEnd = null,
40+
staleEnd = null;
41+
42+
return caches[cacheId] = {
43+
44+
put: function(key, value) {
45+
var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
46+
47+
refresh(lruEntry);
48+
49+
if (isUndefined(value)) return;
50+
if (!(key in data)) size++;
51+
data[key] = value;
52+
53+
if (size > capacity) {
54+
this.remove(staleEnd.key);
55+
}
56+
},
57+
58+
59+
get: function(key) {
60+
var lruEntry = lruHash[key];
61+
62+
if (!lruEntry) return;
63+
64+
refresh(lruEntry);
65+
66+
return data[key];
67+
},
68+
69+
70+
remove: function(key) {
71+
var lruEntry = lruHash[key];
72+
73+
if (lruEntry == freshEnd) freshEnd = lruEntry.p;
74+
if (lruEntry == staleEnd) staleEnd = lruEntry.n;
75+
link(lruEntry.n,lruEntry.p);
76+
77+
delete lruHash[key];
78+
delete data[key];
79+
size--;
80+
},
81+
82+
83+
removeAll: function() {
84+
data = {};
85+
size = 0;
86+
lruHash = {};
87+
freshEnd = staleEnd = null;
88+
},
89+
90+
91+
destroy: function() {
92+
data = null;
93+
stats = null;
94+
lruHash = null;
95+
delete caches[cacheId];
96+
},
97+
98+
99+
info: function() {
100+
return extend({}, stats, {size: size});
101+
}
102+
};
103+
104+
105+
/**
106+
* makes the `entry` the freshEnd of the LRU linked list
107+
*/
108+
function refresh(entry) {
109+
if (entry != freshEnd) {
110+
if (!staleEnd) {
111+
staleEnd = entry;
112+
} else if (staleEnd == entry) {
113+
staleEnd = entry.n;
114+
}
115+
116+
link(entry.n, entry.p);
117+
link(entry, freshEnd);
118+
freshEnd = entry;
119+
freshEnd.n = null;
120+
}
121+
}
122+
123+
124+
/**
125+
* bidirectionally links two entries of the LRU linked list
126+
*/
127+
function link(nextEntry, prevEntry) {
128+
if (nextEntry != prevEntry) {
129+
if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
130+
if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
131+
}
132+
}
133+
}
134+
135+
136+
cacheFactory.info = function() {
137+
var info = {};
138+
forEach(caches, function(cache, cacheId) {
139+
info[cacheId] = cache.info();
140+
});
141+
return info;
142+
};
143+
144+
145+
cacheFactory.get = function(cacheId) {
146+
return caches[cacheId];
147+
};
148+
149+
150+
return cacheFactory;
151+
});

0 commit comments

Comments
 (0)