@woosh/meep-engine 2.82.0 → 2.84.0
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/build/meep.cjs +6 -0
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +6 -0
- package/package.json +1 -1
- package/src/core/collection/RingBuffer.js +6 -0
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +13 -7
- package/src/core/collection/map/AsyncLoadingCache.js +0 -50
- package/src/core/collection/map/AsyncRemoteHashMap.js +0 -358
- package/src/core/collection/map/CachedAsyncMap.js +0 -43
- package/src/core/collection/map/CachedAsyncMap.spec.js +0 -47
package/build/meep.module.js
CHANGED
|
@@ -85688,6 +85688,12 @@ class RingBuffer {
|
|
|
85688
85688
|
* @param {number} new_size
|
|
85689
85689
|
*/
|
|
85690
85690
|
resize(new_size) {
|
|
85691
|
+
|
|
85692
|
+
if (new_size === this.size) {
|
|
85693
|
+
// already the right size
|
|
85694
|
+
return;
|
|
85695
|
+
}
|
|
85696
|
+
|
|
85691
85697
|
const array = new Array(new_size);
|
|
85692
85698
|
|
|
85693
85699
|
this.data = array;
|
package/package.json
CHANGED
|
@@ -6,9 +6,10 @@ import { bvh_query_leaves_ray } from "../../../../../core/bvh2/bvh3/query/bvh_qu
|
|
|
6
6
|
import {
|
|
7
7
|
bvh_query_user_data_overlaps_frustum
|
|
8
8
|
} from "../../../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_frustum.js";
|
|
9
|
-
import {
|
|
9
|
+
import { LoadingCache } from "../../../../../core/cache/LoadingCache.js";
|
|
10
10
|
|
|
11
11
|
import { returnTrue } from "../../../../../core/function/returnTrue.js";
|
|
12
|
+
import { strictEquals } from "../../../../../core/function/strictEquals.js";
|
|
12
13
|
import { aabb3_matrix4_project } from "../../../../../core/geom/3d/aabb/aabb3_matrix4_project.js";
|
|
13
14
|
import { aabb3_raycast } from "../../../../../core/geom/3d/aabb/aabb3_raycast.js";
|
|
14
15
|
import {
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
import { ray3_array_apply_matrix4 } from "../../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
|
|
18
19
|
import { ray3_array_compose } from "../../../../../core/geom/3d/ray/ray3_array_compose.js";
|
|
19
20
|
import { SurfacePoint3 } from "../../../../../core/geom/3d/SurfacePoint3.js";
|
|
21
|
+
import { computeStringHash } from "../../../../../core/primitives/strings/computeStringHash.js";
|
|
20
22
|
import { AssetManager } from "../../../../asset/AssetManager.js";
|
|
21
23
|
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
22
24
|
import { AbstractContextSystem } from "../../../../ecs/system/AbstractContextSystem.js";
|
|
@@ -241,15 +243,19 @@ export class FPDecalSystem extends AbstractContextSystem {
|
|
|
241
243
|
|
|
242
244
|
/**
|
|
243
245
|
*
|
|
244
|
-
* @type {
|
|
246
|
+
* @type {LoadingCache<string, Sampler2D>}
|
|
245
247
|
* @private
|
|
246
248
|
*/
|
|
247
|
-
this.__texture_cache = new
|
|
248
|
-
|
|
249
|
-
|
|
249
|
+
this.__texture_cache = new LoadingCache({
|
|
250
|
+
load: (key) => {
|
|
251
|
+
return this.__assets.promise(key, GameAssetType.Image).then(asset => {
|
|
252
|
+
const asset_sampler = asset.create();
|
|
250
253
|
|
|
251
|
-
|
|
252
|
-
|
|
254
|
+
return sampler2d_ensure_uint8_RGBA(asset_sampler);
|
|
255
|
+
});
|
|
256
|
+
},
|
|
257
|
+
keyHashFunction: computeStringHash,
|
|
258
|
+
keyEqualityFunction: strictEquals
|
|
253
259
|
});
|
|
254
260
|
|
|
255
261
|
/**
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { AbstractAsyncMap } from "./AbstractAsyncMap.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Cache wrapper that loads data when it's not found in the cache
|
|
5
|
-
* @deprecated prefer to use {@link LoadingCache} instead
|
|
6
|
-
*/
|
|
7
|
-
export class AsyncLoadingCache extends AbstractAsyncMap {
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param {Map} cache
|
|
11
|
-
* @param {function(K):Promise<T>} loader
|
|
12
|
-
*/
|
|
13
|
-
constructor(cache, loader) {
|
|
14
|
-
super();
|
|
15
|
-
|
|
16
|
-
this.__cache = cache;
|
|
17
|
-
this.__loader = loader;
|
|
18
|
-
this.__pending = new Map();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async get(key) {
|
|
22
|
-
|
|
23
|
-
const cached = this.__cache.get(key);
|
|
24
|
-
|
|
25
|
-
if (cached !== undefined) {
|
|
26
|
-
return cached;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let promise = this.__pending.get(key);
|
|
30
|
-
let original_loader = false;
|
|
31
|
-
|
|
32
|
-
if (promise === undefined) {
|
|
33
|
-
promise = this.__loader(key);
|
|
34
|
-
|
|
35
|
-
this.__pending.set(key, promise);
|
|
36
|
-
|
|
37
|
-
original_loader = true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const value = await promise;
|
|
41
|
-
|
|
42
|
-
if (original_loader) {
|
|
43
|
-
this.__cache.set(key, value);
|
|
44
|
-
// remove from pending
|
|
45
|
-
this.__pending.delete(key);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return value;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
import { assert } from "../../assert.js";
|
|
2
|
-
import { BinaryBuffer } from "../../binary/BinaryBuffer.js";
|
|
3
|
-
import { AbstractAsyncMap } from "./AbstractAsyncMap.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @template Key,Value
|
|
7
|
-
*/
|
|
8
|
-
export class AsyncRemoteHashMap extends AbstractAsyncMap {
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* @param keyHashFunction
|
|
13
|
-
* @param keyEqualityFunction
|
|
14
|
-
* @param {BinaryClassSerializationAdapter} keySerializationAdapter
|
|
15
|
-
* @param {BinaryClassSerializationAdapter} valueSerializationAdapter
|
|
16
|
-
* @param storageKeyPrefix
|
|
17
|
-
* @param {Storage} storage
|
|
18
|
-
*/
|
|
19
|
-
constructor({
|
|
20
|
-
keyHashFunction,
|
|
21
|
-
keyEqualityFunction,
|
|
22
|
-
keySerializationAdapter,
|
|
23
|
-
valueSerializationAdapter,
|
|
24
|
-
storageKeyPrefix,
|
|
25
|
-
storage
|
|
26
|
-
}) {
|
|
27
|
-
super();
|
|
28
|
-
|
|
29
|
-
assert.isString(storageKeyPrefix, 'storageKeyPrefix');
|
|
30
|
-
|
|
31
|
-
this._keyHashFunction = keyHashFunction;
|
|
32
|
-
this._keyEqualityFunction = keyEqualityFunction;
|
|
33
|
-
this._keySerializationAdapter = keySerializationAdapter;
|
|
34
|
-
this._valueSerializationAdapter = valueSerializationAdapter;
|
|
35
|
-
this._storageKeyPrefix = storageKeyPrefix;
|
|
36
|
-
this._storage = storage;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
* @type {Map<number,Promise>}
|
|
41
|
-
* @private
|
|
42
|
-
*/
|
|
43
|
-
this._bucket_locks = new Map();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* @param {Storage} storage
|
|
49
|
-
*/
|
|
50
|
-
attach_storage(storage) {
|
|
51
|
-
this._storage = storage;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
detach_storage() {
|
|
55
|
-
this._storage = null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async __get_bucket_lock(hash) {
|
|
59
|
-
let source_lock = this._bucket_locks.get(hash);
|
|
60
|
-
if (source_lock === undefined) {
|
|
61
|
-
source_lock = Promise.resolve();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
let is_resolved = false;
|
|
65
|
-
const lock_object = {
|
|
66
|
-
release() {
|
|
67
|
-
is_resolved = true;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const release_promise = new Promise((resolve, reject) => {
|
|
72
|
-
lock_object.release = resolve;
|
|
73
|
-
|
|
74
|
-
if (is_resolved) {
|
|
75
|
-
resolve();
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const new_lock = source_lock.then(() => release_promise);
|
|
80
|
-
|
|
81
|
-
this._bucket_locks.set(hash, new_lock);
|
|
82
|
-
|
|
83
|
-
await source_lock;
|
|
84
|
-
|
|
85
|
-
return lock_object;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* @param {number} hash
|
|
90
|
-
* @return {Promise<ArrayBuffer|undefined>}
|
|
91
|
-
* @private
|
|
92
|
-
*/
|
|
93
|
-
__get_bucket_binary(hash) {
|
|
94
|
-
return this._storage.promiseLoadBinary(this.__compute_bucket_storage_key(hash)).catch(() => {
|
|
95
|
-
return undefined;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
__compute_bucket_storage_key(hash) {
|
|
100
|
-
return `${this._storageKeyPrefix}/${hash}`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
*
|
|
105
|
-
* @param {number} hash
|
|
106
|
-
* @param {ArrayBuffer} bucket
|
|
107
|
-
* @return {Promise}
|
|
108
|
-
* @private
|
|
109
|
-
*/
|
|
110
|
-
__set_bucket_binary(hash, bucket) {
|
|
111
|
-
return this._storage.promiseStoreBinary(this.__compute_bucket_storage_key(hash), bucket);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
*
|
|
116
|
-
* @param {Key} key
|
|
117
|
-
* @param {Value|undefined} value
|
|
118
|
-
* @param {ArrayBuffer} buffer
|
|
119
|
-
* @return {ArrayBuffer}
|
|
120
|
-
* @private
|
|
121
|
-
*/
|
|
122
|
-
__set_value_by_key_in_bucket(key, value, buffer) {
|
|
123
|
-
const source = new BinaryBuffer();
|
|
124
|
-
source.fromArrayBuffer(buffer);
|
|
125
|
-
|
|
126
|
-
const record_count = buffer.byteLength >= 2 ? source.readUint16() : 0;
|
|
127
|
-
|
|
128
|
-
let new_record_count = record_count;
|
|
129
|
-
|
|
130
|
-
// first attempt to find the key
|
|
131
|
-
const existing_value_address = this.__get_value_offset_from_bucket_by_key(key, buffer);
|
|
132
|
-
|
|
133
|
-
if (existing_value_address === -1) {
|
|
134
|
-
new_record_count++;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const destination = new BinaryBuffer();
|
|
138
|
-
destination.writeUint16(new_record_count);
|
|
139
|
-
|
|
140
|
-
let destination_data_offset = 2 + 16 * new_record_count;
|
|
141
|
-
let write_cursor = 0;
|
|
142
|
-
// copy old record over
|
|
143
|
-
for (let i = 0; i < record_count; i++) {
|
|
144
|
-
source.position = 2 + i * 16;
|
|
145
|
-
|
|
146
|
-
const key_position = source.readUint32();
|
|
147
|
-
const key_length = source.readUint32();
|
|
148
|
-
const value_position = source.readUint32();
|
|
149
|
-
const value_length = source.readUint32();
|
|
150
|
-
|
|
151
|
-
if (existing_value_address !== -1 && value_position === existing_value_address) {
|
|
152
|
-
// skip
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// write key + value
|
|
157
|
-
destination.position = 2 + write_cursor * 16;
|
|
158
|
-
|
|
159
|
-
// write header section
|
|
160
|
-
destination.writeUint32(destination_data_offset);
|
|
161
|
-
destination.writeUint32(key_length);
|
|
162
|
-
destination.writeUint32(destination_data_offset + key_length);
|
|
163
|
-
destination.writeUint32(value_length);
|
|
164
|
-
|
|
165
|
-
destination.position = destination_data_offset;
|
|
166
|
-
source.position = key_position;
|
|
167
|
-
BinaryBuffer.copyBytes(source, destination, key_length);
|
|
168
|
-
|
|
169
|
-
destination_data_offset += key_length;
|
|
170
|
-
|
|
171
|
-
destination.position = destination_data_offset;
|
|
172
|
-
source.position = value_position;
|
|
173
|
-
BinaryBuffer.copyBytes(source, destination, value_length);
|
|
174
|
-
|
|
175
|
-
destination_data_offset += value_length;
|
|
176
|
-
|
|
177
|
-
write_cursor++;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const inserted_key_address = destination_data_offset;
|
|
181
|
-
const inserted_key_length = this.__encode_object(destination, inserted_key_address, key, this._keySerializationAdapter);
|
|
182
|
-
|
|
183
|
-
destination_data_offset += inserted_key_length;
|
|
184
|
-
const inserted_value_address = destination_data_offset;
|
|
185
|
-
const inserted_value_length = this.__encode_object(destination, inserted_value_address, value, this._valueSerializationAdapter);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// write section for the new value
|
|
189
|
-
destination.position = 2 + 16 * write_cursor;
|
|
190
|
-
destination.writeUint32(inserted_key_address);
|
|
191
|
-
destination.writeUint32(inserted_key_length);
|
|
192
|
-
destination.writeUint32(inserted_value_address);
|
|
193
|
-
destination.writeUint32(inserted_value_length);
|
|
194
|
-
|
|
195
|
-
// restore position
|
|
196
|
-
destination.position = inserted_value_address + inserted_value_length;
|
|
197
|
-
|
|
198
|
-
destination.trim();
|
|
199
|
-
|
|
200
|
-
return destination.data;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
*
|
|
205
|
-
* @param {Key} key
|
|
206
|
-
* @param {ArrayBuffer} buffer
|
|
207
|
-
* @return {number} -1 if not found, otherwise address within the buffer where the value can be read
|
|
208
|
-
* @private
|
|
209
|
-
*/
|
|
210
|
-
__get_value_offset_from_bucket_by_key(key, buffer) {
|
|
211
|
-
const binary = new BinaryBuffer();
|
|
212
|
-
binary.fromArrayBuffer(buffer);
|
|
213
|
-
|
|
214
|
-
if (binary.length < 2) {
|
|
215
|
-
return -1;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const record_count = binary.readUint16();
|
|
219
|
-
|
|
220
|
-
if (record_count === 0) {
|
|
221
|
-
return -1;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const key_offsets = new Uint32Array(record_count);
|
|
225
|
-
const value_offsets = new Uint32Array(record_count);
|
|
226
|
-
|
|
227
|
-
// read record offsets
|
|
228
|
-
for (let i = 0; i < record_count; i++) {
|
|
229
|
-
const key_offset = binary.readUint32();
|
|
230
|
-
const key_length = binary.readUint32();
|
|
231
|
-
|
|
232
|
-
const value_offset = binary.readUint32();
|
|
233
|
-
const value_length = binary.readUint32();
|
|
234
|
-
|
|
235
|
-
key_offsets[i] = key_offset;
|
|
236
|
-
value_offsets[i] = value_offset;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// read key
|
|
240
|
-
for (let i = 0; i < record_count; i++) {
|
|
241
|
-
const key_address = key_offsets[i];
|
|
242
|
-
|
|
243
|
-
const stored_key = this.__decode_object(binary, key_address, this._keySerializationAdapter);
|
|
244
|
-
|
|
245
|
-
if (this._keyEqualityFunction(stored_key, key)) {
|
|
246
|
-
return value_offsets[i]
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return -1;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
*
|
|
255
|
-
* @param {BinaryBuffer} buffer
|
|
256
|
-
* @param {number} address
|
|
257
|
-
* @param {BinaryClassSerializationAdapter} adapter
|
|
258
|
-
* @return {Value}
|
|
259
|
-
* @private
|
|
260
|
-
*/
|
|
261
|
-
__decode_object(buffer, address, adapter) {
|
|
262
|
-
|
|
263
|
-
buffer.position = address;
|
|
264
|
-
|
|
265
|
-
const ValueKlass = adapter.getClass();
|
|
266
|
-
|
|
267
|
-
const value = new ValueKlass();
|
|
268
|
-
|
|
269
|
-
adapter.deserialize(buffer, value);
|
|
270
|
-
|
|
271
|
-
return value;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @template T
|
|
276
|
-
* @param {BinaryBuffer} buffer
|
|
277
|
-
* @param {number} address
|
|
278
|
-
* @param {T} value
|
|
279
|
-
* @param {BinaryClassSerializationAdapter} adapter
|
|
280
|
-
* @returns {number} bytes written
|
|
281
|
-
* @private
|
|
282
|
-
*/
|
|
283
|
-
__encode_object(buffer, address, value, adapter) {
|
|
284
|
-
buffer.position = address;
|
|
285
|
-
|
|
286
|
-
adapter.serialize(buffer, value);
|
|
287
|
-
|
|
288
|
-
const bytes_written = buffer.position - address;
|
|
289
|
-
|
|
290
|
-
return bytes_written;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
*
|
|
295
|
-
* @param {BinaryBuffer} buffer
|
|
296
|
-
* @param {number} address
|
|
297
|
-
* @return {Value}
|
|
298
|
-
* @private
|
|
299
|
-
*/
|
|
300
|
-
__decode_value(buffer, address) {
|
|
301
|
-
return this.__decode_object(buffer, address, this._valueSerializationAdapter);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
*
|
|
306
|
-
* @param {Key} key
|
|
307
|
-
* @return {Promise<Value|undefined>}
|
|
308
|
-
*/
|
|
309
|
-
async get(key) {
|
|
310
|
-
// hash the key to identify bucket to load
|
|
311
|
-
const key_hash = this._keyHashFunction(key);
|
|
312
|
-
|
|
313
|
-
const lock = await this.__get_bucket_lock(key_hash);
|
|
314
|
-
|
|
315
|
-
const bucket_buffer = await this.__get_bucket_binary(key_hash);
|
|
316
|
-
|
|
317
|
-
lock.release();
|
|
318
|
-
|
|
319
|
-
if (bucket_buffer === undefined) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const value_address = this.__get_value_offset_from_bucket_by_key(key, bucket_buffer);
|
|
324
|
-
|
|
325
|
-
if (value_address === -1) {
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
const binary = new BinaryBuffer();
|
|
330
|
-
binary.fromArrayBuffer(bucket_buffer);
|
|
331
|
-
|
|
332
|
-
return this.__decode_value(binary, value_address);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
*
|
|
337
|
-
* @param {Key} key
|
|
338
|
-
* @param {Value} value
|
|
339
|
-
* @return {Promise<void>}
|
|
340
|
-
*/
|
|
341
|
-
async set(key, value) {
|
|
342
|
-
const key_hash = this._keyHashFunction(key);
|
|
343
|
-
|
|
344
|
-
const lock = await this.__get_bucket_lock(key_hash);
|
|
345
|
-
|
|
346
|
-
let bucket_buffer = await this.__get_bucket_binary(key_hash);
|
|
347
|
-
|
|
348
|
-
if (bucket_buffer === undefined) {
|
|
349
|
-
bucket_buffer = new ArrayBuffer(0);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const updated_buffer = this.__set_value_by_key_in_bucket(key, value, bucket_buffer);
|
|
353
|
-
|
|
354
|
-
await this.__set_bucket_binary(key_hash, updated_buffer);
|
|
355
|
-
|
|
356
|
-
lock.release();
|
|
357
|
-
}
|
|
358
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { AbstractAsyncMap } from "./AbstractAsyncMap.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Two-tier key-value storage. Intended to accelerate slow asynchronous
|
|
5
|
-
* storage with a fast but limited (in space and reliability) cache in front.
|
|
6
|
-
*
|
|
7
|
-
* First tier (volatile) is considered to be fast an unreliable,
|
|
8
|
-
* whereas second tier (persisted) is considered to be reliable, but slow.
|
|
9
|
-
*/
|
|
10
|
-
export class CachedAsyncMap extends AbstractAsyncMap {
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param {AbstractAsyncMap} volatile data here may be lost at any point, this is our "cache"
|
|
14
|
-
* @param {AbstractAsyncMap} persisted data here is stored reliably
|
|
15
|
-
*/
|
|
16
|
-
constructor(volatile, persisted) {
|
|
17
|
-
super();
|
|
18
|
-
|
|
19
|
-
this.__volatile = volatile;
|
|
20
|
-
this.__persisted = persisted;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async get(key) {
|
|
24
|
-
const volatile_value = await this.__volatile.get(key);
|
|
25
|
-
|
|
26
|
-
if (volatile_value !== undefined && volatile_value !== null) {
|
|
27
|
-
return volatile_value;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// TODO re-insert into volatile if persisted has a hit
|
|
31
|
-
|
|
32
|
-
return await this.__persisted.get(key);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async set(key, value) {
|
|
36
|
-
const lock = this.__volatile.set(key, value);
|
|
37
|
-
|
|
38
|
-
// don't wait for completion on persisted
|
|
39
|
-
this.__persisted.set(key, value);
|
|
40
|
-
|
|
41
|
-
await lock;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { CachedAsyncMap } from "./CachedAsyncMap.js";
|
|
2
|
-
import { AsyncMapWrapper } from "./AsyncMapWrapper.js";
|
|
3
|
-
|
|
4
|
-
test("'get' retrieves data if it is available in volatile level", async () => {
|
|
5
|
-
|
|
6
|
-
const first = new Map();
|
|
7
|
-
|
|
8
|
-
const sut = new CachedAsyncMap(new AsyncMapWrapper(first), new AsyncMapWrapper());
|
|
9
|
-
|
|
10
|
-
first.set(1, 3);
|
|
11
|
-
|
|
12
|
-
expect(await sut.get(1)).toBe(3);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("'get' retrieves data if it is available in persisted level", async () => {
|
|
16
|
-
|
|
17
|
-
const second = new Map();
|
|
18
|
-
|
|
19
|
-
const sut = new CachedAsyncMap(new AsyncMapWrapper(), new AsyncMapWrapper(second));
|
|
20
|
-
|
|
21
|
-
second.set(1, 3);
|
|
22
|
-
|
|
23
|
-
expect(await sut.get(1)).toBe(3);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("'set' propagates data into volatile level", async () => {
|
|
27
|
-
|
|
28
|
-
const first = new Map();
|
|
29
|
-
|
|
30
|
-
const sut = new CachedAsyncMap(new AsyncMapWrapper(first), new AsyncMapWrapper());
|
|
31
|
-
|
|
32
|
-
await sut.set(1, 3);
|
|
33
|
-
|
|
34
|
-
expect(first.get(1)).toBe(3);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
test("'set' propagates data into persisted level", async () => {
|
|
39
|
-
|
|
40
|
-
const second = new Map();
|
|
41
|
-
|
|
42
|
-
const sut = new CachedAsyncMap(new AsyncMapWrapper(), new AsyncMapWrapper(second));
|
|
43
|
-
|
|
44
|
-
await sut.set(1, 3);
|
|
45
|
-
|
|
46
|
-
expect(second.get(1)).toBe(3);
|
|
47
|
-
});
|