@woosh/meep-engine 2.49.4 → 2.49.6

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 CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.49.4",
8
+ "version": "2.49.6",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1,18 +1,19 @@
1
- export declare class LoadingCache<K,V>{
2
- constructor(options:{
1
+ export declare class LoadingCache<K, V> {
2
+ constructor(options: {
3
3
  maxWeight?: number,
4
4
  keyWeigher?: (key: K) => number,
5
5
  valueWeigher?: (value: V) => number,
6
6
  keyHashFunction?: (key: K) => number,
7
7
  keyEqualityFunction?: (a: K, b: K) => boolean,
8
8
  capacity?: number,
9
- timeToLive?:number,
10
- load:(key:K)=> Promise<V>
9
+ timeToLive?: number,
10
+ load: (key: K) => Promise<V>,
11
+ retryFailed?: boolean
11
12
  })
12
13
 
13
- invalidate(key:K):void
14
+ invalidate(key: K): void
14
15
 
15
- clear():void
16
+ clear(): void
16
17
 
17
- get(key:K):Promise<V>
18
+ get(key: K): Promise<V>
18
19
  }
@@ -3,17 +3,18 @@
3
3
  import { Cache } from "./Cache.js";
4
4
 
5
5
  /**
6
- * @template {V}
6
+ * @template R
7
7
  */
8
8
  class Record {
9
9
  /**
10
- *
11
- * @param {V} value
10
+ * @template R
11
+ * @param {R} value
12
12
  * @param {number} time
13
13
  */
14
14
  constructor(value, time) {
15
15
  this.value = value;
16
16
  this.time = time;
17
+ this.failed = false;
17
18
  }
18
19
  }
19
20
 
@@ -38,6 +39,12 @@ export class LoadingCache {
38
39
  */
39
40
  #load
40
41
 
42
+ /**
43
+ *
44
+ * @type {boolean}
45
+ */
46
+ #policyRetryFailed = true;
47
+
41
48
  /**
42
49
  * @see {@link Cache} for more details on what each parameter means
43
50
  * @param maxWeight
@@ -48,6 +55,7 @@ export class LoadingCache {
48
55
  * @param capacity
49
56
  * @param {number} [timeToLive] in seconds
50
57
  * @param load
58
+ * @param {boolean} [retryFailed]
51
59
  */
52
60
  constructor({
53
61
  maxWeight,
@@ -57,7 +65,8 @@ export class LoadingCache {
57
65
  keyEqualityFunction,
58
66
  capacity,
59
67
  timeToLive = DEFAULT_TIME_TO_LIVE,
60
- load
68
+ load,
69
+ retryFailed = true
61
70
  }) {
62
71
 
63
72
  this.#internal = new Cache({
@@ -71,6 +80,7 @@ export class LoadingCache {
71
80
 
72
81
  this.#timeToLive = timeToLive;
73
82
  this.#load = load;
83
+ this.#policyRetryFailed = retryFailed;
74
84
  }
75
85
 
76
86
  /**
@@ -96,17 +106,36 @@ export class LoadingCache {
96
106
  async get(key) {
97
107
  const currentTime = performance.now() * 1e-3;
98
108
 
109
+ /**
110
+ *
111
+ * @type {Record<Promise<V>>}
112
+ */
99
113
  let record = this.#internal.get(key);
100
114
 
101
- if (record === null || (record.time + this.#timeToLive) < currentTime) {
115
+ if (record === null
116
+ || (record.time + this.#timeToLive) < currentTime // timeout
117
+ || (record.failed && this.#policyRetryFailed) // load failed and we're configured to retry
118
+ ) {
119
+
120
+ // record needs to be loaded
102
121
 
103
- // missing or stale record
104
- const promise = this.#load(key);
122
+ let promise;
123
+
124
+ try {
125
+ promise = this.#load(key);
126
+ }catch (e){
127
+ promise = Promise.reject(e);
128
+ }
105
129
 
106
130
  record = new Record(promise, currentTime);
107
131
 
108
132
  this.#internal.put(key, record);
109
133
 
134
+ promise.catch(() => {
135
+ // mark as failure
136
+ record.failed = true;
137
+ });
138
+
110
139
  }
111
140
 
112
141
 
@@ -0,0 +1,47 @@
1
+ import { LoadingCache } from "./LoadingCache.js";
2
+ import { delay } from "../process/delay.js";
3
+
4
+ test("successful load", async () => {
5
+ const cache = new LoadingCache({
6
+ async load(key) {
7
+ return 17;
8
+ }
9
+ });
10
+
11
+ expect(await cache.get(1)).toEqual(17);
12
+ });
13
+
14
+ test("record reuse", async () => {
15
+ const load = jest.fn(async () => 17);
16
+
17
+ const cache = new LoadingCache({
18
+ load
19
+ });
20
+
21
+ expect(await cache.get(1)).toEqual(17);
22
+ expect(await cache.get(1)).toEqual(17);
23
+
24
+ expect(load).toHaveBeenCalledTimes(1);
25
+ });
26
+
27
+ test("timeout reload reuse", async () => {
28
+
29
+ const values = [3, 5, 11];
30
+
31
+ const load = jest.fn(async () => values.pop());
32
+
33
+ const cache = new LoadingCache({
34
+ load,
35
+ timeToLive: 0.00001
36
+ });
37
+
38
+ expect(await cache.get(1)).toEqual(11);
39
+
40
+ await delay(1);
41
+
42
+ expect(await cache.get(1)).toEqual(5);
43
+
44
+ await delay(1);
45
+
46
+ expect(await cache.get(1)).toEqual(3);
47
+ });