@hkdigital/lib-sveltekit 0.1.95 → 0.1.97
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.
@@ -38,16 +38,19 @@
|
|
38
38
|
|
39
39
|
/** @typedef {import('./typedef').IDBVersionChangeEvent} IDBVersionChangeEvent */
|
40
40
|
|
41
|
-
const DEFAULT_DB_NAME ='http-cache';
|
42
|
-
const DEFAULT_STORE_NAME ='responses';
|
43
|
-
const DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
|
44
|
-
const DEFAULT_MAX_AGE = 90 * 24 * 60 * 60 * 1000;
|
41
|
+
const DEFAULT_DB_NAME = 'http-cache';
|
42
|
+
const DEFAULT_STORE_NAME = 'responses';
|
43
|
+
const DEFAULT_MAX_SIZE = 50 * 1024 * 1024; // 50 MB
|
44
|
+
const DEFAULT_MAX_AGE = 90 * 24 * 60 * 60 * 1000; // 90 days
|
45
45
|
|
46
46
|
const DEFAULT_CLEANUP_BATCH_SIZE = 100;
|
47
47
|
const DEFAULT_CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes;
|
48
48
|
|
49
49
|
const DEFAULT_CLEANUP_POSTPONE_MS = 5000; // 5 seconds
|
50
50
|
|
51
|
+
// Add logging to track concurrent access
|
52
|
+
const concurrentReadsByKey = new Map();
|
53
|
+
|
51
54
|
/**
|
52
55
|
* IndexedDbCache with automatic background cleanup
|
53
56
|
*/
|
@@ -72,10 +75,12 @@ export default class IndexedDbCache {
|
|
72
75
|
this.maxSize = options.maxSize || DEFAULT_MAX_SIZE;
|
73
76
|
this.maxAge = options.maxAge || DEFAULT_MAX_AGE;
|
74
77
|
|
75
|
-
this.cleanupBatchSize =
|
78
|
+
this.cleanupBatchSize =
|
79
|
+
options.cleanupBatchSize || DEFAULT_CLEANUP_BATCH_SIZE;
|
76
80
|
this.cleanupInterval = options.cleanupInterval || DEFAULT_CLEANUP_INTERVAL;
|
77
81
|
|
78
|
-
this.cleanupPostponeTimeout =
|
82
|
+
this.cleanupPostponeTimeout =
|
83
|
+
options.cleanupPostponeTimeout || DEFAULT_CLEANUP_POSTPONE_MS;
|
79
84
|
this.cacheVersion = options.cacheVersion || '1.0.0';
|
80
85
|
|
81
86
|
// Define index names as constants to ensure consistency
|
@@ -318,10 +323,15 @@ export default class IndexedDbCache {
|
|
318
323
|
* @returns {Promise<CacheEntry|null>} Cache entry or null if not found/expired
|
319
324
|
*/
|
320
325
|
async get(key) {
|
326
|
+
// Track concurrent reads per key
|
327
|
+
const current = concurrentReadsByKey.get(key) || 0;
|
328
|
+
concurrentReadsByKey.set(key, current + 1);
|
329
|
+
console.log(`Concurrent reads for ${key}: ${current + 1}`);
|
330
|
+
|
321
331
|
try {
|
322
332
|
const db = await this.dbPromise;
|
323
333
|
|
324
|
-
|
334
|
+
const result = new Promise((resolve, reject) => {
|
325
335
|
try {
|
326
336
|
const transaction = db.transaction(this.storeName, 'readonly');
|
327
337
|
const store = transaction.objectStore(this.storeName);
|
@@ -421,9 +431,22 @@ export default class IndexedDbCache {
|
|
421
431
|
resolve(null);
|
422
432
|
}
|
423
433
|
});
|
434
|
+
|
435
|
+
return result;
|
424
436
|
} catch (err) {
|
425
437
|
console.error('Cache get error:', err);
|
426
438
|
return null;
|
439
|
+
} finally {
|
440
|
+
// Always decrement
|
441
|
+
const current = concurrentReadsByKey.get(key) || 1;
|
442
|
+
if (current <= 1) {
|
443
|
+
concurrentReadsByKey.delete(key);
|
444
|
+
} else {
|
445
|
+
concurrentReadsByKey.set(key, current - 1);
|
446
|
+
}
|
447
|
+
console.log(
|
448
|
+
`Concurrent reads for ${key} after decrement: ${current - 1}`
|
449
|
+
);
|
427
450
|
}
|
428
451
|
}
|
429
452
|
|
@@ -490,7 +513,7 @@ export default class IndexedDbCache {
|
|
490
513
|
// Calculate rough size estimate
|
491
514
|
const headerSize = JSON.stringify(headers).length * 2;
|
492
515
|
const size =
|
493
|
-
/** @type {Blob} */ (
|
516
|
+
/** @type {Blob} */ (body.size || 0) + headerSize + key.length * 2;
|
494
517
|
|
495
518
|
const entry = {
|
496
519
|
key,
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/** @typedef {import('../../../typedef/image.js').ImageMeta} ImageMeta */
|
1
2
|
export default class ImageVariantsLoader {
|
2
3
|
/**
|
3
4
|
* @param {ImageMeta[]} imagesMeta
|
@@ -19,7 +20,7 @@ export default class ImageVariantsLoader {
|
|
19
20
|
fit?: "cover" | "contain" | "fill";
|
20
21
|
}): void;
|
21
22
|
get loaded(): boolean;
|
22
|
-
get variant(): import("
|
23
|
+
get variant(): import("../../../typedef/image.js").ImageMeta;
|
23
24
|
/**
|
24
25
|
* Get object URL that can be used as src parameter of an HTML image
|
25
26
|
*
|
@@ -39,4 +40,4 @@ export default class ImageVariantsLoader {
|
|
39
40
|
getOptimalImageMeta(containerWidth: number): ImageMeta | null;
|
40
41
|
#private;
|
41
42
|
}
|
42
|
-
export type ImageMeta = import("
|
43
|
+
export type ImageMeta = import("../../../typedef/image.js").ImageMeta;
|
@@ -1,13 +1,9 @@
|
|
1
|
-
/** @typedef {import('./typedef.js').ImageMeta} ImageMeta */
|
2
|
-
|
3
|
-
// import * as expect from '../../../util/expect/index.js';
|
4
|
-
|
5
1
|
import { calculateEffectiveWidth } from '../../../util/image/index.js';
|
6
2
|
|
7
|
-
import { untrack } from 'svelte';
|
8
|
-
|
9
3
|
import ImageLoader from './ImageLoader.svelte.js';
|
10
4
|
|
5
|
+
/** @typedef {import('../../../typedef/image.js').ImageMeta} ImageMeta */
|
6
|
+
|
11
7
|
export default class ImageVariantsLoader {
|
12
8
|
/** @type {number} */
|
13
9
|
#devicePixelRatio;
|
@@ -37,6 +33,7 @@ export default class ImageVariantsLoader {
|
|
37
33
|
constructor(imagesMeta, { devicePixelRatio = 1 } = {}) {
|
38
34
|
this.#devicePixelRatio = devicePixelRatio ?? 1;
|
39
35
|
this.#imagesMeta = [...imagesMeta].sort((a, b) => a.width - b.width);
|
36
|
+
// console.debug("imagesMeta",imagesMeta);
|
40
37
|
}
|
41
38
|
|
42
39
|
/**
|
@@ -60,6 +57,8 @@ export default class ImageVariantsLoader {
|
|
60
57
|
|
61
58
|
const newVariant = this.getOptimalImageMeta(effectiveWidth);
|
62
59
|
|
60
|
+
// console.debug("updateOptimalImageMeta", effectiveWidth, newVariant );
|
61
|
+
|
63
62
|
if (
|
64
63
|
!newVariant ||
|
65
64
|
!this.#imageVariant ||
|
@@ -76,6 +75,7 @@ export default class ImageVariantsLoader {
|
|
76
75
|
imageMeta: newVariant
|
77
76
|
});
|
78
77
|
|
78
|
+
|
79
79
|
this.#imageLoader.load();
|
80
80
|
}
|
81
81
|
}
|
@@ -87,6 +87,7 @@ export default class NetworkLoader {
|
|
87
87
|
this._url = url;
|
88
88
|
|
89
89
|
const state = this._state;
|
90
|
+
const progress = this.progress;
|
90
91
|
|
91
92
|
//
|
92
93
|
// ISSUE: $effect is not triggered by this._state changes,
|
@@ -110,10 +111,15 @@ export default class NetworkLoader {
|
|
110
111
|
|
111
112
|
case STATE_LOADED:
|
112
113
|
{
|
113
|
-
// console.
|
114
|
-
|
115
|
-
//
|
116
|
-
//
|
114
|
+
// console.debug('NetworkLoader:loaded', $state.snapshot(state));
|
115
|
+
|
116
|
+
// setTimeout(() => {
|
117
|
+
// console.debug(
|
118
|
+
// 'NetworkLoader:loaded',
|
119
|
+
// $state.snapshot(state),
|
120
|
+
// progress
|
121
|
+
// );
|
122
|
+
// }, 500);
|
117
123
|
|
118
124
|
// Abort function is no longer needed
|
119
125
|
this._abortLoading = null;
|
@@ -140,7 +146,7 @@ export default class NetworkLoader {
|
|
140
146
|
* Start loading all network data
|
141
147
|
*/
|
142
148
|
load() {
|
143
|
-
// console.
|
149
|
+
// console.debug('NetworkLoader: load() called');
|
144
150
|
this._state.send(LOAD);
|
145
151
|
}
|
146
152
|
|
@@ -301,6 +307,8 @@ export default class NetworkLoader {
|
|
301
307
|
|
302
308
|
this._buffer = await bufferPromise;
|
303
309
|
|
310
|
+
// console.debug('#load', this._buffer, this._bytesLoaded);
|
311
|
+
|
304
312
|
this._state.send(LOADED);
|
305
313
|
} catch (e) {
|
306
314
|
this._state.send(ERROR, e);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@hkdigital/lib-sveltekit",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.97",
|
4
4
|
"author": {
|
5
5
|
"name": "HKdigital",
|
6
6
|
"url": "https://hkdigital.nl"
|
@@ -105,7 +105,7 @@
|
|
105
105
|
"tailwindcss": "^3.4.17",
|
106
106
|
"typescript": "^5.8.2",
|
107
107
|
"vite": "^6.2.0",
|
108
|
-
"vite-imagetools": "^7.0
|
108
|
+
"vite-imagetools": "^7.1.0",
|
109
109
|
"vitest": "^3.0.7",
|
110
110
|
"zod": "^3.24.2"
|
111
111
|
}
|