@devvit/cache 0.12.1-next-2025-10-09-21-45-29-add2ad79f.0 → 0.12.1-next-2025-10-09-23-10-17-c0793c292.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/PromiseCache.d.ts +1 -1
- package/PromiseCache.js +23 -23
- package/package.json +6 -6
package/PromiseCache.d.ts
CHANGED
package/PromiseCache.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _PromiseCache_instances, _PromiseCache_redis, _PromiseCache_localCache, _PromiseCache_clock, _PromiseCache_randomizer, _PromiseCache_localCachedAnswer, _PromiseCache_maybeRefreshCache, _PromiseCache_refreshCache, _PromiseCache_pollForCache, _PromiseCache_updateCache, _PromiseCache_calculateRamp, _PromiseCache_redisEntry
|
|
12
|
+
var _PromiseCache_instances, _PromiseCache_redis, _PromiseCache_localCache, _PromiseCache_clock, _PromiseCache_randomizer, _PromiseCache_localCachedAnswer, _PromiseCache_maybeRefreshCache, _PromiseCache_refreshCache, _PromiseCache_pollForCache, _PromiseCache_updateCache, _PromiseCache_calculateRamp, _PromiseCache_redisEntry;
|
|
13
13
|
// Isolate the random() method to avoid passing the Math package around
|
|
14
14
|
export const MathRandomizer = {
|
|
15
15
|
random() {
|
|
@@ -27,9 +27,9 @@ export function _namespaced(key) {
|
|
|
27
27
|
export function _lock(key) {
|
|
28
28
|
return `__devvit_cache_lock__${key}`;
|
|
29
29
|
}
|
|
30
|
+
const minTtlMsValue = 5000; // milliseconds
|
|
30
31
|
const pollEvery = 300; // milliseconds
|
|
31
32
|
const maxPollingTimeout = 1000; // milliseconds
|
|
32
|
-
const minTtlValue = 5000; // milliseconds
|
|
33
33
|
export const retryLimit = 3;
|
|
34
34
|
const errorRetryProbability = 0.1;
|
|
35
35
|
export const clientRetryDelay = 1000; // milliseconds
|
|
@@ -101,13 +101,18 @@ export class PromiseCache {
|
|
|
101
101
|
* - SET __lock__${key} '1' and DEL __lock__${key} to acquire and release a lock for a given key
|
|
102
102
|
*/
|
|
103
103
|
async cache(closure, options) {
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
const { key } = options;
|
|
105
|
+
let ttlMs = options.ttl * 1000; // convert to milliseconds without mutating the original options object
|
|
106
|
+
if (ttlMs < minTtlMsValue) {
|
|
107
|
+
console.warn(`Cache TTL cannot be less than ${minTtlMsValue / 1000} seconds! Updating ttl value to ${minTtlMsValue / 1000} seconds.`);
|
|
108
|
+
ttlMs = minTtlMsValue;
|
|
109
|
+
}
|
|
110
|
+
const localCachedAnswer = __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_localCachedAnswer).call(this, key);
|
|
106
111
|
if (localCachedAnswer !== undefined) {
|
|
107
112
|
return localCachedAnswer;
|
|
108
113
|
}
|
|
109
|
-
const existing = await __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_redisEntry).call(this,
|
|
110
|
-
const entry = await __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_maybeRefreshCache).call(this,
|
|
114
|
+
const existing = await __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_redisEntry).call(this, key);
|
|
115
|
+
const entry = await __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_maybeRefreshCache).call(this, key, ttlMs, existing, closure);
|
|
111
116
|
return _unwrap(entry);
|
|
112
117
|
}
|
|
113
118
|
}
|
|
@@ -137,7 +142,7 @@ _PromiseCache_redis = new WeakMap(), _PromiseCache_localCache = new WeakMap(), _
|
|
|
137
142
|
*
|
|
138
143
|
* We'll always refresh if missing or expired, but its probabilistic if we'll refresh if about to expire or if we have an error.
|
|
139
144
|
*/
|
|
140
|
-
async function _PromiseCache_maybeRefreshCache(
|
|
145
|
+
async function _PromiseCache_maybeRefreshCache(key, ttlMs, entry, closure) {
|
|
141
146
|
const expires = entry?.expires;
|
|
142
147
|
const rampProbability = expires ? __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_calculateRamp).call(this, expires) : 1;
|
|
143
148
|
if (!entry ||
|
|
@@ -145,7 +150,7 @@ async function _PromiseCache_maybeRefreshCache(options, entry, closure) {
|
|
|
145
150
|
entry.errorCount < retryLimit &&
|
|
146
151
|
errorRetryProbability > __classPrivateFieldGet(this, _PromiseCache_randomizer, "f").random()) ||
|
|
147
152
|
rampProbability > __classPrivateFieldGet(this, _PromiseCache_randomizer, "f").random()) {
|
|
148
|
-
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_refreshCache).call(this,
|
|
153
|
+
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_refreshCache).call(this, key, ttlMs, entry, closure);
|
|
149
154
|
}
|
|
150
155
|
else {
|
|
151
156
|
return entry;
|
|
@@ -157,19 +162,19 @@ async function _PromiseCache_maybeRefreshCache(options, entry, closure) {
|
|
|
157
162
|
*
|
|
158
163
|
* If you don't win the lock, you'll poll for the cache. If you don't get the cache within maxPollingTimeout, you'll throw an error.
|
|
159
164
|
*/
|
|
160
|
-
async function _PromiseCache_refreshCache(
|
|
161
|
-
const lockKey = _lock(
|
|
165
|
+
async function _PromiseCache_refreshCache(key, ttlMs, entry, closure) {
|
|
166
|
+
const lockKey = _lock(key);
|
|
162
167
|
const now = __classPrivateFieldGet(this, _PromiseCache_clock, "f").now().getTime();
|
|
163
168
|
/**
|
|
164
169
|
* The write lock should last for a while, but not the full TTL. Hopefully write attempts settle down after a while.
|
|
165
170
|
*/
|
|
166
|
-
const lockExpiration = new Date(now +
|
|
171
|
+
const lockExpiration = new Date(now + ttlMs / 2);
|
|
167
172
|
const lockObtained = await __classPrivateFieldGet(this, _PromiseCache_redis, "f").set(lockKey, '1', {
|
|
168
173
|
expiration: lockExpiration,
|
|
169
174
|
nx: true,
|
|
170
175
|
});
|
|
171
176
|
if (lockObtained) {
|
|
172
|
-
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_updateCache).call(this,
|
|
177
|
+
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_updateCache).call(this, key, entry, closure, ttlMs);
|
|
173
178
|
}
|
|
174
179
|
else if (entry) {
|
|
175
180
|
// This entry is still valid, return it
|
|
@@ -177,10 +182,10 @@ async function _PromiseCache_refreshCache(options, entry, closure) {
|
|
|
177
182
|
}
|
|
178
183
|
else {
|
|
179
184
|
const start = __classPrivateFieldGet(this, _PromiseCache_clock, "f").now();
|
|
180
|
-
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_pollForCache).call(this, start,
|
|
185
|
+
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_pollForCache).call(this, start, key, ttlMs);
|
|
181
186
|
}
|
|
182
|
-
}, _PromiseCache_pollForCache = async function _PromiseCache_pollForCache(start, key,
|
|
183
|
-
const pollingTimeout = Math.min(
|
|
187
|
+
}, _PromiseCache_pollForCache = async function _PromiseCache_pollForCache(start, key, ttlMs) {
|
|
188
|
+
const pollingTimeout = Math.min(ttlMs, maxPollingTimeout);
|
|
184
189
|
const existing = await __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_redisEntry).call(this, key);
|
|
185
190
|
if (existing) {
|
|
186
191
|
return existing;
|
|
@@ -189,13 +194,13 @@ async function _PromiseCache_refreshCache(options, entry, closure) {
|
|
|
189
194
|
throw new Error(`Cache request timed out trying to get data at key: ${key}`);
|
|
190
195
|
}
|
|
191
196
|
await new Promise((resolve) => setTimeout(resolve, pollEvery));
|
|
192
|
-
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_pollForCache).call(this, start, key,
|
|
197
|
+
return __classPrivateFieldGet(this, _PromiseCache_instances, "m", _PromiseCache_pollForCache).call(this, start, key, ttlMs);
|
|
193
198
|
}, _PromiseCache_updateCache =
|
|
194
199
|
/**
|
|
195
200
|
* Actually update the cache. This is the method that will be called if we have the lock.
|
|
196
201
|
*/
|
|
197
|
-
async function _PromiseCache_updateCache(key, entry, closure,
|
|
198
|
-
const expires = __classPrivateFieldGet(this, _PromiseCache_clock, "f").now().getTime() +
|
|
202
|
+
async function _PromiseCache_updateCache(key, entry, closure, ttlMs) {
|
|
203
|
+
const expires = __classPrivateFieldGet(this, _PromiseCache_clock, "f").now().getTime() + ttlMs;
|
|
199
204
|
entry = entry ?? {
|
|
200
205
|
value: null,
|
|
201
206
|
expires,
|
|
@@ -255,9 +260,4 @@ async function _PromiseCache_updateCache(key, entry, closure, ttl) {
|
|
|
255
260
|
return entry;
|
|
256
261
|
}
|
|
257
262
|
return undefined;
|
|
258
|
-
}, _PromiseCache_enforceTTL = function _PromiseCache_enforceTTL(options) {
|
|
259
|
-
if (options.ttl < minTtlValue) {
|
|
260
|
-
console.warn(`Cache TTL cannot be less than ${minTtlValue} milliseconds! Updating ttl value of ${options.ttl} to ${minTtlValue}.`);
|
|
261
|
-
options.ttl = minTtlValue;
|
|
262
|
-
}
|
|
263
263
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devvit/cache",
|
|
3
|
-
"version": "0.12.1-next-2025-10-09-
|
|
3
|
+
"version": "0.12.1-next-2025-10-09-23-10-17-c0793c292.0",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"test:unit-with-coverage": "vitest run --coverage"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@devvit/redis": "0.12.1-next-2025-10-09-
|
|
35
|
-
"@devvit/shared-types": "0.12.1-next-2025-10-09-
|
|
34
|
+
"@devvit/redis": "0.12.1-next-2025-10-09-23-10-17-c0793c292.0",
|
|
35
|
+
"@devvit/shared-types": "0.12.1-next-2025-10-09-23-10-17-c0793c292.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@devvit/repo-tools": "0.12.1-next-2025-10-09-
|
|
39
|
-
"@devvit/tsconfig": "0.12.1-next-2025-10-09-
|
|
38
|
+
"@devvit/repo-tools": "0.12.1-next-2025-10-09-23-10-17-c0793c292.0",
|
|
39
|
+
"@devvit/tsconfig": "0.12.1-next-2025-10-09-23-10-17-c0793c292.0",
|
|
40
40
|
"eslint": "9.11.1",
|
|
41
41
|
"typescript": "5.8.3",
|
|
42
42
|
"vitest": "1.6.1"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "704e966f3a13c15799c23625bb48ebeef2f8e2bd"
|
|
45
45
|
}
|