@twin.org/core 0.9.3-next.3 → 0.9.3-next.5
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/dist/es/index.js +1 -0
- package/dist/es/index.js.map +1 -1
- package/dist/es/models/IMutexWaiter.js +4 -0
- package/dist/es/models/IMutexWaiter.js.map +1 -0
- package/dist/es/utils/lfuCache.js +91 -13
- package/dist/es/utils/lfuCache.js.map +1 -1
- package/dist/es/utils/lruCache.js +83 -10
- package/dist/es/utils/lruCache.js.map +1 -1
- package/dist/es/utils/mutex.js +170 -23
- package/dist/es/utils/mutex.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/models/IMutexWaiter.d.ts +17 -0
- package/dist/types/utils/lfuCache.d.ts +8 -2
- package/dist/types/utils/lruCache.d.ts +8 -2
- package/dist/types/utils/mutex.d.ts +9 -0
- package/docs/changelog.md +34 -0
- package/docs/reference/classes/LfuCache.md +18 -2
- package/docs/reference/classes/LruCache.md +18 -2
- package/docs/reference/classes/Mutex.md +9 -0
- package/docs/reference/index.md +1 -0
- package/docs/reference/interfaces/IMutexWaiter.md +37 -0
- package/locales/en.json +1 -1
- package/package.json +2 -2
|
@@ -10,6 +10,8 @@ minimum frequency is evicted.
|
|
|
10
10
|
The timer only runs while there are entries; it stops automatically when the cache empties.
|
|
11
11
|
|
|
12
12
|
`get` and `set` increment an entry's access frequency and reset its idle timer.
|
|
13
|
+
`set` and `getOrSet` accept an optional hard expiry timestamp; the entry is removed once that
|
|
14
|
+
time is reached however recently it was used, and the TTI still applies alongside it.
|
|
13
15
|
`has` and `keys` are pure peeks they evict idle entries but do not affect frequency or TTI.
|
|
14
16
|
Call `destroy` when the cache is no longer needed to stop the background timer.
|
|
15
17
|
|
|
@@ -125,7 +127,7 @@ The cached value, or undefined on a miss or idle eviction.
|
|
|
125
127
|
|
|
126
128
|
### set() {#set}
|
|
127
129
|
|
|
128
|
-
> **set**(`key`, `value`): `void`
|
|
130
|
+
> **set**(`key`, `value`, `expires?`): `void`
|
|
129
131
|
|
|
130
132
|
Store a value in the cache.
|
|
131
133
|
If the key already exists its value and frequency are updated.
|
|
@@ -146,6 +148,13 @@ The key to store.
|
|
|
146
148
|
|
|
147
149
|
The value to cache.
|
|
148
150
|
|
|
151
|
+
##### expires?
|
|
152
|
+
|
|
153
|
+
`number`
|
|
154
|
+
|
|
155
|
+
Hard expiry timestamp in milliseconds since the epoch. The entry is removed
|
|
156
|
+
once this time is reached regardless of how recently it was used. Must be an integer.
|
|
157
|
+
|
|
149
158
|
#### Returns
|
|
150
159
|
|
|
151
160
|
`void`
|
|
@@ -154,7 +163,7 @@ The value to cache.
|
|
|
154
163
|
|
|
155
164
|
### getOrSet() {#getorset}
|
|
156
165
|
|
|
157
|
-
> **getOrSet**(`key`, `valueFactory`): `Promise`\<`T`\>
|
|
166
|
+
> **getOrSet**(`key`, `valueFactory`, `expires?`): `Promise`\<`T`\>
|
|
158
167
|
|
|
159
168
|
Atomically get an existing value or create and store it once using an async factory.
|
|
160
169
|
Concurrent calls for the same key are serialized via a mutex.
|
|
@@ -173,6 +182,13 @@ The key to get or create.
|
|
|
173
182
|
|
|
174
183
|
Async callback used to build a value when the key is absent.
|
|
175
184
|
|
|
185
|
+
##### expires?
|
|
186
|
+
|
|
187
|
+
`number`
|
|
188
|
+
|
|
189
|
+
Hard expiry timestamp in milliseconds since the epoch, applied to the entry
|
|
190
|
+
when one is created. Must be an integer.
|
|
191
|
+
|
|
176
192
|
#### Returns
|
|
177
193
|
|
|
178
194
|
`Promise`\<`T`\>
|
|
@@ -8,6 +8,8 @@ Entries are removed in two ways:
|
|
|
8
8
|
The timer only runs while there are entries; it stops automatically when the cache empties.
|
|
9
9
|
|
|
10
10
|
`get` and `set` both update an entry's LRU position and reset its idle timer.
|
|
11
|
+
`set` and `getOrSet` accept an optional hard expiry timestamp; the entry is removed once that
|
|
12
|
+
time is reached however recently it was used, and the TTI still applies alongside it.
|
|
11
13
|
`has` is a pure peek it evicts idle entries but does not refresh a live entry's TTI.
|
|
12
14
|
Call `destroy` when the cache is no longer needed to stop the background timer.
|
|
13
15
|
|
|
@@ -123,7 +125,7 @@ The cached value, or undefined on a miss or idle eviction.
|
|
|
123
125
|
|
|
124
126
|
### set() {#set}
|
|
125
127
|
|
|
126
|
-
> **set**(`key`, `value`): `void`
|
|
128
|
+
> **set**(`key`, `value`, `expires?`): `void`
|
|
127
129
|
|
|
128
130
|
Store a value in the cache.
|
|
129
131
|
If the key already exists its value and idle timer are refreshed.
|
|
@@ -144,6 +146,13 @@ The key to store.
|
|
|
144
146
|
|
|
145
147
|
The value to cache.
|
|
146
148
|
|
|
149
|
+
##### expires?
|
|
150
|
+
|
|
151
|
+
`number`
|
|
152
|
+
|
|
153
|
+
Hard expiry timestamp in milliseconds since the epoch. The entry is removed
|
|
154
|
+
once this time is reached regardless of how recently it was used. Must be an integer.
|
|
155
|
+
|
|
147
156
|
#### Returns
|
|
148
157
|
|
|
149
158
|
`void`
|
|
@@ -152,7 +161,7 @@ The value to cache.
|
|
|
152
161
|
|
|
153
162
|
### getOrSet() {#getorset}
|
|
154
163
|
|
|
155
|
-
> **getOrSet**(`key`, `valueFactory`): `Promise`\<`T`\>
|
|
164
|
+
> **getOrSet**(`key`, `valueFactory`, `expires?`): `Promise`\<`T`\>
|
|
156
165
|
|
|
157
166
|
Atomically get an existing value or create and store it once using an async factory.
|
|
158
167
|
Concurrent calls for the same key are serialized via a mutex.
|
|
@@ -171,6 +180,13 @@ The key to get or create.
|
|
|
171
180
|
|
|
172
181
|
Async callback used to build a value when the key is absent.
|
|
173
182
|
|
|
183
|
+
##### expires?
|
|
184
|
+
|
|
185
|
+
`number`
|
|
186
|
+
|
|
187
|
+
Hard expiry timestamp in milliseconds since the epoch, applied to the entry
|
|
188
|
+
when one is created. Must be an integer.
|
|
189
|
+
|
|
174
190
|
#### Returns
|
|
175
191
|
|
|
176
192
|
`Promise`\<`T`\>
|
|
@@ -12,6 +12,13 @@ the shared buffer with the main thread on first use of each key, then caches it
|
|
|
12
12
|
The main thread must call Mutex.handleWorkerMessage(msg) from its worker message handler
|
|
13
13
|
before that worker first calls Mutex.lock().
|
|
14
14
|
|
|
15
|
+
Callers on the same thread are served in the order they arrived. Each key has a FIFO
|
|
16
|
+
queue of waiters, unlock() hands the lock directly to the waiter at the front, and a new
|
|
17
|
+
caller only takes the lock outright when that queue is empty. Without this a caller that
|
|
18
|
+
arrives while a waiter is being woken can take the lock first, which lets a busy key
|
|
19
|
+
starve a waiter until its timeout elapses. Threads still contend with each other for the
|
|
20
|
+
shared lock, so the ordering guarantee is per thread rather than global.
|
|
21
|
+
|
|
15
22
|
The lock is not re-entrant: a thread that already holds a key and calls lock() again on
|
|
16
23
|
the same key will block until the timeout elapses.
|
|
17
24
|
|
|
@@ -81,6 +88,8 @@ Acquires a lock for the given key without blocking the event loop. If the lock i
|
|
|
81
88
|
held, it suspends the current async task until the lock is released or the timeout is reached.
|
|
82
89
|
Use this in async single-threaded contexts (e.g. the main thread or a Fastify route handler)
|
|
83
90
|
where calling the synchronous lock() would freeze the event loop and deadlock.
|
|
91
|
+
Callers on the same thread are served in the order they arrived, so a contended key
|
|
92
|
+
cannot starve an earlier caller.
|
|
84
93
|
The lock is not re-entrant: if the same context holds the key and calls lockAsync() again on
|
|
85
94
|
the same key, it will suspend until the timeout elapses.
|
|
86
95
|
|
package/docs/reference/index.md
CHANGED
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
- [ILocale](interfaces/ILocale.md)
|
|
60
60
|
- [ILocaleDictionary](interfaces/ILocaleDictionary.md)
|
|
61
61
|
- [ILocalesIndex](interfaces/ILocalesIndex.md)
|
|
62
|
+
- [IMutexWaiter](interfaces/IMutexWaiter.md)
|
|
62
63
|
- [IMutexWorkerMessage](interfaces/IMutexWorkerMessage.md)
|
|
63
64
|
- [IPatchOperation](interfaces/IPatchOperation.md)
|
|
64
65
|
- [ISharedObjectBufferOptions](interfaces/ISharedObjectBufferOptions.md)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Interface: IMutexWaiter
|
|
2
|
+
|
|
3
|
+
A caller queued on a mutex key, waiting to be handed the lock.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
### settled {#settled}
|
|
8
|
+
|
|
9
|
+
> **settled**: `boolean`
|
|
10
|
+
|
|
11
|
+
Has the waiter already been granted the lock or given up waiting.
|
|
12
|
+
|
|
13
|
+
***
|
|
14
|
+
|
|
15
|
+
### resolve? {#resolve}
|
|
16
|
+
|
|
17
|
+
> `optional` **resolve?**: (`granted`) => `void`
|
|
18
|
+
|
|
19
|
+
Resolves the queued caller, true when it now owns the lock.
|
|
20
|
+
|
|
21
|
+
#### Parameters
|
|
22
|
+
|
|
23
|
+
##### granted
|
|
24
|
+
|
|
25
|
+
`boolean`
|
|
26
|
+
|
|
27
|
+
#### Returns
|
|
28
|
+
|
|
29
|
+
`void`
|
|
30
|
+
|
|
31
|
+
***
|
|
32
|
+
|
|
33
|
+
### timer? {#timer}
|
|
34
|
+
|
|
35
|
+
> `optional` **timer?**: `Timeout`
|
|
36
|
+
|
|
37
|
+
Timer which enforces the waiter's deadline.
|
package/locales/en.json
CHANGED
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"mutex": {
|
|
115
115
|
"lockNotFound": "The key \"{key}\" has no active lock",
|
|
116
116
|
"lockAlreadyReleased": "The key \"{key}\" is not currently locked",
|
|
117
|
-
"lockTimeout": "Failed to acquire lock for key \"{key}\" within the timeout of {
|
|
117
|
+
"lockTimeout": "Failed to acquire lock for key \"{key}\" within the timeout of {timeoutMs} milliseconds",
|
|
118
118
|
"bufferFetchFailed": "Failed to retrieve shared buffer for key \"{key}\" from the main thread",
|
|
119
119
|
"invalidTimeout": "The timeout value \"{timeoutMs}\" is invalid, it must be a non-negative integer"
|
|
120
120
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/core",
|
|
3
|
-
"version": "0.9.3-next.
|
|
3
|
+
"version": "0.9.3-next.5",
|
|
4
4
|
"description": "Helper methods/classes for data type checking/validation/guarding/error handling",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"node": ">=24.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twin.org/nameof": "0.9.3-next.
|
|
17
|
+
"@twin.org/nameof": "0.9.3-next.5",
|
|
18
18
|
"intl-messageformat": "11.2.13",
|
|
19
19
|
"rfc6902": "5.3.0"
|
|
20
20
|
},
|