@extra-memoize/memory-cache 0.2.7 → 0.2.9
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/package.json +3 -3
- package/src/caches/expirable-cache-with-stale-if-error.ts +39 -0
- package/src/caches/expirable-cache-with-stale-while-revalidate-and-stale-if-error.ts +51 -0
- package/src/caches/expirable-cache-with-stale-while-revalidate.ts +40 -0
- package/src/caches/expirable-cache.ts +26 -0
- package/src/caches/index.ts +11 -0
- package/src/caches/lru-cache.ts +26 -0
- package/src/caches/tlru-cache-with-stale-if-error.ts +43 -0
- package/src/caches/tlru-cache-with-stale-while-revalidate-and-stale-if-error.ts +52 -0
- package/src/caches/tlru-cache-with-stale-while-revalidate.ts +44 -0
- package/src/caches/tlru-cache.ts +26 -0
- package/src/index.ts +1 -0
- package/dist/es2015/index.min.mjs +0 -2
- package/dist/es2015/index.min.mjs.map +0 -1
- package/dist/es2015/index.mjs +0 -22850
- package/dist/es2015/index.mjs.map +0 -1
- package/dist/es2015/index.umd.js +0 -22868
- package/dist/es2015/index.umd.js.map +0 -1
- package/dist/es2015/index.umd.min.js +0 -2
- package/dist/es2015/index.umd.min.js.map +0 -1
- package/dist/es2018/index.min.mjs +0 -2
- package/dist/es2018/index.min.mjs.map +0 -1
- package/dist/es2018/index.mjs +0 -22850
- package/dist/es2018/index.mjs.map +0 -1
- package/dist/es2018/index.umd.js +0 -22868
- package/dist/es2018/index.umd.js.map +0 -1
- package/dist/es2018/index.umd.min.js +0 -2
- package/dist/es2018/index.umd.min.js.map +0 -1
package/package.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "@extra-memoize/memory-cache",
|
3
|
-
"version": "0.2.
|
3
|
+
"version": "0.2.9",
|
4
4
|
"description": "",
|
5
5
|
"keywords": [],
|
6
6
|
"files": [
|
7
7
|
"lib",
|
8
|
-
"
|
8
|
+
"src"
|
9
9
|
],
|
10
10
|
"main": "lib/es2018/index.js",
|
11
11
|
"types": "lib/es2018/index.d.ts",
|
@@ -56,7 +56,7 @@
|
|
56
56
|
"typescript": "^4.8.4"
|
57
57
|
},
|
58
58
|
"dependencies": {
|
59
|
-
"@blackglory/prelude": "^0.2.
|
59
|
+
"@blackglory/prelude": "^0.2.4",
|
60
60
|
"@blackglory/structures": "^0.11.3"
|
61
61
|
},
|
62
62
|
"peerDependencies": {
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { ExpirableCache } from './expirable-cache'
|
2
|
+
import { IStaleIfErrorCache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
interface IRecord<T> {
|
5
|
+
updatedAt: number
|
6
|
+
value: T
|
7
|
+
}
|
8
|
+
|
9
|
+
export class ExpirableCacheWithStaleIfError<T> implements IStaleIfErrorCache<T> {
|
10
|
+
private cache: ExpirableCache<IRecord<T>>
|
11
|
+
|
12
|
+
constructor(private timeToLive: number, private staleIfError: number) {
|
13
|
+
this.cache = new ExpirableCache(timeToLive + staleIfError)
|
14
|
+
}
|
15
|
+
|
16
|
+
set(key: string, value: T): void {
|
17
|
+
this.cache.set(key, {
|
18
|
+
value
|
19
|
+
, updatedAt: Date.now()
|
20
|
+
})
|
21
|
+
}
|
22
|
+
|
23
|
+
get(key: string): [State.Miss] | [State.Hit | State.StaleIfError, T] {
|
24
|
+
const [state, record] = this.cache.get(key)
|
25
|
+
if (state === State.Miss) {
|
26
|
+
return [State.Miss]
|
27
|
+
} else {
|
28
|
+
const elapsed = Date.now() - record.updatedAt
|
29
|
+
if (elapsed <= this.timeToLive) {
|
30
|
+
return [State.Hit, record.value]
|
31
|
+
} else if (elapsed <= this.timeToLive + this.staleIfError) {
|
32
|
+
return [State.StaleIfError, record.value]
|
33
|
+
} else {
|
34
|
+
// just in case
|
35
|
+
return [State.Miss]
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { ExpirableCache } from './expirable-cache'
|
2
|
+
import { IStaleWhileRevalidateAndStaleIfErrorCache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
interface IRecord<T> {
|
5
|
+
updatedAt: number
|
6
|
+
value: T
|
7
|
+
}
|
8
|
+
|
9
|
+
export class ExpirableCacheWithStaleWhileRevalidateAndStaleIfError<T> implements IStaleWhileRevalidateAndStaleIfErrorCache<T> {
|
10
|
+
private cache: ExpirableCache<IRecord<T>>
|
11
|
+
|
12
|
+
constructor(
|
13
|
+
private timeToLive: number
|
14
|
+
, private staleWhileRevalidate: number
|
15
|
+
, private staleIfError: number
|
16
|
+
) {
|
17
|
+
this.cache = new ExpirableCache(timeToLive + staleWhileRevalidate + staleIfError)
|
18
|
+
}
|
19
|
+
|
20
|
+
set(key: string, value: T): void {
|
21
|
+
this.cache.set(key, {
|
22
|
+
value
|
23
|
+
, updatedAt: Date.now()
|
24
|
+
})
|
25
|
+
}
|
26
|
+
|
27
|
+
get(key: string): [State.Miss]
|
28
|
+
| [
|
29
|
+
| State.Hit
|
30
|
+
| State.StaleWhileRevalidate
|
31
|
+
| State.StaleIfError
|
32
|
+
, T
|
33
|
+
] {
|
34
|
+
const [state, record] = this.cache.get(key)
|
35
|
+
if (state === State.Miss) {
|
36
|
+
return [State.Miss]
|
37
|
+
} else {
|
38
|
+
const elapsed = Date.now() - record.updatedAt
|
39
|
+
if (elapsed <= this.timeToLive) {
|
40
|
+
return [State.Hit, record.value]
|
41
|
+
} else if (elapsed <= this.timeToLive + this.staleWhileRevalidate) {
|
42
|
+
return [State.StaleWhileRevalidate, record.value]
|
43
|
+
} else if (elapsed <= this.timeToLive + this.staleWhileRevalidate + this.staleIfError) {
|
44
|
+
return [State.StaleIfError, record.value]
|
45
|
+
} else {
|
46
|
+
// just in case
|
47
|
+
return [State.Miss]
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { ExpirableCache } from './expirable-cache'
|
2
|
+
import { IStaleWhileRevalidateCache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
interface IRecord<T> {
|
5
|
+
updatedAt: number
|
6
|
+
value: T
|
7
|
+
}
|
8
|
+
|
9
|
+
export class ExpirableCacheWithStaleWhileRevalidate<T> implements IStaleWhileRevalidateCache<T> {
|
10
|
+
private cache: ExpirableCache<IRecord<T>>
|
11
|
+
|
12
|
+
constructor(private timeToLive: number, private staleWhileRevalidate: number) {
|
13
|
+
this.cache = new ExpirableCache(timeToLive + staleWhileRevalidate)
|
14
|
+
}
|
15
|
+
|
16
|
+
set(key: string, value: T): void {
|
17
|
+
this.cache.set(key, {
|
18
|
+
value
|
19
|
+
, updatedAt: Date.now()
|
20
|
+
})
|
21
|
+
}
|
22
|
+
|
23
|
+
get(key: string): [State.Miss] | [State.Hit | State.StaleWhileRevalidate, T] {
|
24
|
+
const [state, record] = this.cache.get(key)
|
25
|
+
if (state === State.Miss) {
|
26
|
+
return [State.Miss]
|
27
|
+
} else {
|
28
|
+
if (this.isStaleWhileRevalidate(record)) {
|
29
|
+
return [State.StaleWhileRevalidate, record.value]
|
30
|
+
} else {
|
31
|
+
return [State.Hit, record.value]
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
private isStaleWhileRevalidate(record: IRecord<T>): boolean {
|
37
|
+
return Date.now() - record.updatedAt > this.timeToLive
|
38
|
+
&& Date.now() - record.updatedAt <= this.timeToLive + this.staleWhileRevalidate
|
39
|
+
}
|
40
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { ExpirableMap } from '@blackglory/structures'
|
2
|
+
import { ICache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
export class ExpirableCache<T> implements ICache<T> {
|
5
|
+
private map: ExpirableMap<string, T>
|
6
|
+
|
7
|
+
constructor(private timeToLive: number) {
|
8
|
+
this.map = new ExpirableMap()
|
9
|
+
}
|
10
|
+
|
11
|
+
get(key: string): [State.Miss] | [State.Hit, T] {
|
12
|
+
if (this.map.has(key)) {
|
13
|
+
return [State.Hit, this.map.get(key)!]
|
14
|
+
} else {
|
15
|
+
return [State.Miss]
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
set(key: string, value: T): void {
|
20
|
+
this.map.set(key, value, this.timeToLive)
|
21
|
+
}
|
22
|
+
|
23
|
+
clear(): void {
|
24
|
+
this.map.clear()
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
export * from './lru-cache'
|
2
|
+
|
3
|
+
export * from './expirable-cache'
|
4
|
+
export * from './expirable-cache-with-stale-while-revalidate'
|
5
|
+
export * from './expirable-cache-with-stale-if-error'
|
6
|
+
export * from './expirable-cache-with-stale-while-revalidate-and-stale-if-error'
|
7
|
+
|
8
|
+
export * from './tlru-cache'
|
9
|
+
export * from './tlru-cache-with-stale-while-revalidate'
|
10
|
+
export * from './tlru-cache-with-stale-if-error'
|
11
|
+
export * from './tlru-cache-with-stale-while-revalidate-and-stale-if-error'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { LRUMap } from '@blackglory/structures'
|
2
|
+
import { ICache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
export class LRUCache<T> implements ICache<T> {
|
5
|
+
private map: LRUMap<string, T>
|
6
|
+
|
7
|
+
constructor(limit: number) {
|
8
|
+
this.map = new LRUMap(limit)
|
9
|
+
}
|
10
|
+
|
11
|
+
set(key: string, value: T): void {
|
12
|
+
this.map.set(key, value)
|
13
|
+
}
|
14
|
+
|
15
|
+
get(key: string): [State.Miss] | [State.Hit, T] {
|
16
|
+
if (this.map.has(key)) {
|
17
|
+
return [State.Hit, this.map.get(key)!]
|
18
|
+
} else {
|
19
|
+
return [State.Miss]
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
clear(): void {
|
24
|
+
this.map.clear()
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { TLRUCache } from './tlru-cache'
|
2
|
+
import { IStaleIfErrorCache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
interface IRecord<T> {
|
5
|
+
updatedAt: number
|
6
|
+
value: T
|
7
|
+
}
|
8
|
+
|
9
|
+
export class TLRUCacheWithStaleIfError<T> implements IStaleIfErrorCache<T> {
|
10
|
+
private cache: TLRUCache<IRecord<T>>
|
11
|
+
|
12
|
+
constructor(
|
13
|
+
limit: number
|
14
|
+
, private timeToLive: number
|
15
|
+
, private staleIfError: number
|
16
|
+
) {
|
17
|
+
this.cache = new TLRUCache(limit, timeToLive + staleIfError)
|
18
|
+
}
|
19
|
+
|
20
|
+
set(key: string, value: T): void {
|
21
|
+
this.cache.set(key, {
|
22
|
+
value
|
23
|
+
, updatedAt: Date.now()
|
24
|
+
})
|
25
|
+
}
|
26
|
+
|
27
|
+
get(key: string): [State.Miss] | [State.Hit | State.StaleIfError, T] {
|
28
|
+
const [state, record] = this.cache.get(key)
|
29
|
+
if (state === State.Miss) {
|
30
|
+
return [State.Miss]
|
31
|
+
} else {
|
32
|
+
const elapsed = Date.now() - record.updatedAt
|
33
|
+
if (elapsed <= this.timeToLive) {
|
34
|
+
return [State.Hit, record.value]
|
35
|
+
} else if (elapsed <= this.timeToLive + this.staleIfError) {
|
36
|
+
return [State.StaleIfError, record.value]
|
37
|
+
} else {
|
38
|
+
// just in case
|
39
|
+
return [State.Miss]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import { TLRUCache } from './tlru-cache'
|
2
|
+
import { IStaleWhileRevalidateAndStaleIfErrorCache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
interface IRecord<T> {
|
5
|
+
updatedAt: number
|
6
|
+
value: T
|
7
|
+
}
|
8
|
+
|
9
|
+
export class TLRUCacheWithStaleWhileRevalidateAndStaleIfError<T> implements IStaleWhileRevalidateAndStaleIfErrorCache<T> {
|
10
|
+
private cache: TLRUCache<IRecord<T>>
|
11
|
+
|
12
|
+
constructor(
|
13
|
+
limit: number
|
14
|
+
, private timeToLive: number
|
15
|
+
, private staleWhileRevalidate: number
|
16
|
+
, private staleIfError: number
|
17
|
+
) {
|
18
|
+
this.cache = new TLRUCache(limit, timeToLive + staleWhileRevalidate + staleIfError)
|
19
|
+
}
|
20
|
+
|
21
|
+
set(key: string, value: T): void {
|
22
|
+
this.cache.set(key, {
|
23
|
+
value
|
24
|
+
, updatedAt: Date.now()
|
25
|
+
})
|
26
|
+
}
|
27
|
+
|
28
|
+
get(key: string): [State.Miss]
|
29
|
+
| [
|
30
|
+
| State.Hit
|
31
|
+
| State.StaleWhileRevalidate
|
32
|
+
| State.StaleIfError
|
33
|
+
, T
|
34
|
+
] {
|
35
|
+
const [state, record] = this.cache.get(key)
|
36
|
+
if (state === State.Miss) {
|
37
|
+
return [State.Miss]
|
38
|
+
} else {
|
39
|
+
const elapsed = Date.now() - record.updatedAt
|
40
|
+
if (elapsed <= this.timeToLive) {
|
41
|
+
return [State.Hit, record.value]
|
42
|
+
} else if (elapsed <= this.timeToLive + this.staleWhileRevalidate) {
|
43
|
+
return [State.StaleWhileRevalidate, record.value]
|
44
|
+
} else if (elapsed <= this.timeToLive + this.staleWhileRevalidate + this.staleIfError) {
|
45
|
+
return [State.StaleIfError, record.value]
|
46
|
+
} else {
|
47
|
+
// just in case
|
48
|
+
return [State.Miss]
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { TLRUCache } from './tlru-cache'
|
2
|
+
import { IStaleWhileRevalidateCache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
interface IRecord<T> {
|
5
|
+
updatedAt: number
|
6
|
+
value: T
|
7
|
+
}
|
8
|
+
|
9
|
+
export class TLRUCacheWithStaleWhileRevalidate<T> implements IStaleWhileRevalidateCache<T> {
|
10
|
+
private cache: TLRUCache<IRecord<T>>
|
11
|
+
|
12
|
+
constructor(
|
13
|
+
limit: number
|
14
|
+
, private timeToLive: number
|
15
|
+
, private staleWhileRevalidate: number
|
16
|
+
) {
|
17
|
+
this.cache = new TLRUCache(limit, timeToLive + staleWhileRevalidate)
|
18
|
+
}
|
19
|
+
|
20
|
+
set(key: string, value: T): void {
|
21
|
+
this.cache.set(key, {
|
22
|
+
value
|
23
|
+
, updatedAt: Date.now()
|
24
|
+
})
|
25
|
+
}
|
26
|
+
|
27
|
+
get(key: string): [State.Miss] | [State.Hit | State.StaleWhileRevalidate, T] {
|
28
|
+
const [state, record] = this.cache.get(key)
|
29
|
+
if (state === State.Miss) {
|
30
|
+
return [State.Miss]
|
31
|
+
} else {
|
32
|
+
if (this.isStaleWhileRevalidate(record)) {
|
33
|
+
return [State.StaleWhileRevalidate, record.value]
|
34
|
+
} else {
|
35
|
+
return [State.Hit, record.value]
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
isStaleWhileRevalidate(record: IRecord<T>): boolean {
|
41
|
+
return Date.now() - record.updatedAt > this.timeToLive
|
42
|
+
&& Date.now() - record.updatedAt <= this.timeToLive + this.staleWhileRevalidate
|
43
|
+
}
|
44
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { TLRUMap } from '@blackglory/structures'
|
2
|
+
import { ICache, State } from 'extra-memoize'
|
3
|
+
|
4
|
+
export class TLRUCache<T> implements ICache<T> {
|
5
|
+
private map: TLRUMap<string, T>
|
6
|
+
|
7
|
+
constructor(limit: number, private timeToLive: number) {
|
8
|
+
this.map = new TLRUMap(limit)
|
9
|
+
}
|
10
|
+
|
11
|
+
set(key: string, value: T): void {
|
12
|
+
this.map.set(key, value, this.timeToLive)
|
13
|
+
}
|
14
|
+
|
15
|
+
get(key: string): [State.Miss] | [State.Hit, T] {
|
16
|
+
if (this.map.has(key)) {
|
17
|
+
return [State.Hit, this.map.get(key)!]
|
18
|
+
} else {
|
19
|
+
return [State.Miss]
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
clear(): void {
|
24
|
+
this.map.clear()
|
25
|
+
}
|
26
|
+
}
|
package/src/index.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from '@caches'
|