@asaidimu/utils-sync 2.1.0 → 2.2.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/README.md +50 -50
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ yarn add @asaidimu/utils-sync
|
|
|
70
70
|
After installation, you can test that the library works correctly:
|
|
71
71
|
|
|
72
72
|
```typescript
|
|
73
|
-
import { Mutex } from
|
|
73
|
+
import { Mutex } from "@asaidimu/utils-sync";
|
|
74
74
|
|
|
75
75
|
const mutex = new Mutex();
|
|
76
76
|
console.log(mutex.locked()); // false
|
|
@@ -85,13 +85,13 @@ If the import runs without errors, the package is ready.
|
|
|
85
85
|
All examples assume ES module import syntax:
|
|
86
86
|
|
|
87
87
|
```typescript
|
|
88
|
-
import { Mutex, Once, Serializer } from
|
|
88
|
+
import { Mutex, Once, Serializer } from "@asaidimu/utils-sync";
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
For CommonJS:
|
|
92
92
|
|
|
93
93
|
```javascript
|
|
94
|
-
const { Mutex, Once, Serializer } = require(
|
|
94
|
+
const { Mutex, Once, Serializer } = require("@asaidimu/utils-sync");
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
---
|
|
@@ -125,7 +125,7 @@ try {
|
|
|
125
125
|
mutex.unlock();
|
|
126
126
|
} catch (err) {
|
|
127
127
|
if (err instanceof TimeoutError) {
|
|
128
|
-
console.log(
|
|
128
|
+
console.log("Could not acquire lock in time");
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
```
|
|
@@ -146,20 +146,20 @@ if (mutex.tryLock()) {
|
|
|
146
146
|
|
|
147
147
|
#### Options
|
|
148
148
|
|
|
149
|
-
| Option
|
|
150
|
-
|
|
151
|
-
| `capacity`
|
|
152
|
-
| `yieldMode`
|
|
149
|
+
| Option | Type | Default | Description |
|
|
150
|
+
| ----------- | ------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
151
|
+
| `capacity` | `number` | `Infinity` | Max pending waiters. If exceeded, `lock()` throws an error. |
|
|
152
|
+
| `yieldMode` | `"macrotask"` \| `"microtask"` | `"macrotask"` | `"macrotask"` yields via `setTimeout(…,0)` (prevents starvation). `"microtask"` uses `queueMicrotask` for lower latency. |
|
|
153
153
|
|
|
154
154
|
#### API
|
|
155
155
|
|
|
156
|
-
| Method
|
|
157
|
-
|
|
158
|
-
| `lock(timeout?: number)`
|
|
159
|
-
| `tryLock()`
|
|
160
|
-
| `unlock()`
|
|
161
|
-
| `locked()`
|
|
162
|
-
| `pending()`
|
|
156
|
+
| Method | Return type | Description |
|
|
157
|
+
| ------------------------ | --------------- | ---------------------------------------------------------------------------------------------- |
|
|
158
|
+
| `lock(timeout?: number)` | `Promise<void>` | Acquire lock, waiting if necessary. Throws `TimeoutError` if timeout elapses or queue is full. |
|
|
159
|
+
| `tryLock()` | `boolean` | Attempt to acquire lock without waiting. Returns `true` if acquired. |
|
|
160
|
+
| `unlock()` | `void` | Release the lock. Throws if not locked. Schedules next waiter according to `yieldMode`. |
|
|
161
|
+
| `locked()` | `boolean` | Returns `true` if the lock is currently held. |
|
|
162
|
+
| `pending()` | `number` | Number of tasks waiting for the lock. |
|
|
163
163
|
|
|
164
164
|
---
|
|
165
165
|
|
|
@@ -174,7 +174,7 @@ const once = new Once<string>();
|
|
|
174
174
|
|
|
175
175
|
async function getConfig() {
|
|
176
176
|
const result = await once.do(async () => {
|
|
177
|
-
const res = await fetch(
|
|
177
|
+
const res = await fetch("/api/config");
|
|
178
178
|
return res.json();
|
|
179
179
|
});
|
|
180
180
|
// result.value contains the config, or result.error if failed
|
|
@@ -210,23 +210,23 @@ if (once.ready()) {
|
|
|
210
210
|
|
|
211
211
|
#### Options
|
|
212
212
|
|
|
213
|
-
| Option
|
|
214
|
-
|
|
215
|
-
| `retry`
|
|
216
|
-
| `throws`
|
|
213
|
+
| Option | Type | Default | Description |
|
|
214
|
+
| -------- | --------- | ------- | --------------------------------------------------------------------------------------------------- |
|
|
215
|
+
| `retry` | `boolean` | `false` | If `true`, a failed execution does **not** mark the instance as done – next call will retry. |
|
|
216
|
+
| `throws` | `boolean` | `false` | If `true`, the `do()` method will **throw** the error instead of returning it in the result object. |
|
|
217
217
|
|
|
218
218
|
#### API
|
|
219
219
|
|
|
220
|
-
| Method
|
|
221
|
-
|
|
222
|
-
| `do(fn, timeout?)`
|
|
223
|
-
| `ready()`
|
|
224
|
-
| `running()`
|
|
225
|
-
| `peek()`
|
|
226
|
-
| `get()`
|
|
227
|
-
| `reset()`
|
|
228
|
-
| `done()`
|
|
229
|
-
| `current()`
|
|
220
|
+
| Method | Return type | Description |
|
|
221
|
+
| ------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
222
|
+
| `do(fn, timeout?)` | `Promise<OnceResult<T>>` | Executes `fn` once. Returns `{ value, error }` (unless `throws:true`). Timeout covers lock + execution. |
|
|
223
|
+
| `ready()` | `boolean` | `true` if operation has completed (success or non‑retryable failure) and no execution is running. |
|
|
224
|
+
| `running()` | `boolean` | `true` if the operation is currently executing. |
|
|
225
|
+
| `peek()` | `OnceResult<T>` | Returns current cached `{ value, error }` without waiting. |
|
|
226
|
+
| `get()` | `T \| null` | Returns cached value if done, otherwise throws. Throws cached error if present. |
|
|
227
|
+
| `reset()` | `void` | Clears state – next `do()` will run again. |
|
|
228
|
+
| `done()` | `boolean` | `true` if finished (success or final failure). |
|
|
229
|
+
| `current()` | `Promise<OnceResult<T>> \| null` | Returns the underlying promise if running, otherwise `null`. |
|
|
230
230
|
|
|
231
231
|
---
|
|
232
232
|
|
|
@@ -241,7 +241,7 @@ const serializer = new Serializer<string>();
|
|
|
241
241
|
|
|
242
242
|
async function log(message: string) {
|
|
243
243
|
const result = await serializer.do(async () => {
|
|
244
|
-
await appendToFile(
|
|
244
|
+
await appendToFile("log.txt", message);
|
|
245
245
|
return message;
|
|
246
246
|
});
|
|
247
247
|
return result.value; // last successful result
|
|
@@ -253,8 +253,8 @@ async function log(message: string) {
|
|
|
253
253
|
Even if a task fails, the serializer continues processing the next queued tasks:
|
|
254
254
|
|
|
255
255
|
```typescript
|
|
256
|
-
await serializer.do(failingFn);
|
|
257
|
-
await serializer.do(successfulFn);
|
|
256
|
+
await serializer.do(failingFn); // returns { error: ... }
|
|
257
|
+
await serializer.do(successfulFn); // still runs
|
|
258
258
|
```
|
|
259
259
|
|
|
260
260
|
#### Peeking at the last result
|
|
@@ -273,20 +273,20 @@ const result = await serializer.do(anyFn);
|
|
|
273
273
|
|
|
274
274
|
#### Options
|
|
275
275
|
|
|
276
|
-
| Option
|
|
277
|
-
|
|
278
|
-
| `capacity`
|
|
279
|
-
| `yieldMode`
|
|
276
|
+
| Option | Type | Default | Description |
|
|
277
|
+
| ----------- | ------------------------------ | ------------- | --------------------------------------------------------------------------------- |
|
|
278
|
+
| `capacity` | `number` | `1000` | Max pending tasks. When full, `do()` returns an error immediately. |
|
|
279
|
+
| `yieldMode` | `"macrotask"` \| `"microtask"` | `"macrotask"` | Handoff scheduling for the internal mutex. Default prevents microtask starvation. |
|
|
280
280
|
|
|
281
281
|
#### API
|
|
282
282
|
|
|
283
|
-
| Method
|
|
284
|
-
|
|
285
|
-
| `do(fn, timeout?)`
|
|
286
|
-
| `peek()`
|
|
287
|
-
| `close()`
|
|
288
|
-
| `pending()`
|
|
289
|
-
| `running()`
|
|
283
|
+
| Method | Return type | Description |
|
|
284
|
+
| ------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------- |
|
|
285
|
+
| `do(fn, timeout?)` | `Promise<SerializerResult<T\|null>>` | Enqueues `fn`. Returns `{ value, error }`. If closed or queue full, error is `SerializerExecutionDone`. |
|
|
286
|
+
| `peek()` | `SerializerResult<T\|null>` | Returns the last successful result or last error. |
|
|
287
|
+
| `close()` | `void` | Permanently closes the serializer. All subsequent `do()` calls fail immediately. |
|
|
288
|
+
| `pending()` | `number` | Number of tasks waiting in the queue. |
|
|
289
|
+
| `running()` | `boolean` | `true` if a task is currently executing. |
|
|
290
290
|
|
|
291
291
|
---
|
|
292
292
|
|
|
@@ -328,11 +328,11 @@ npm install
|
|
|
328
328
|
|
|
329
329
|
### Scripts
|
|
330
330
|
|
|
331
|
-
| Command
|
|
332
|
-
|
|
333
|
-
| `npm test`
|
|
334
|
-
| `npm run test:watch`
|
|
335
|
-
| `npm run test:browser` | Run tests in a browser environment (Vitest)
|
|
331
|
+
| Command | Description |
|
|
332
|
+
| ---------------------- | ------------------------------------------- |
|
|
333
|
+
| `npm test` | Run tests once (Vitest) |
|
|
334
|
+
| `npm run test:watch` | Run tests in watch mode |
|
|
335
|
+
| `npm run test:browser` | Run tests in a browser environment (Vitest) |
|
|
336
336
|
|
|
337
337
|
### Testing
|
|
338
338
|
|
|
@@ -372,7 +372,7 @@ Report bugs or request features via [GitHub Issues](https://github.com/asaidimu/
|
|
|
372
372
|
### Troubleshooting
|
|
373
373
|
|
|
374
374
|
| Problem | Possible solution |
|
|
375
|
-
|
|
375
|
+
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
376
376
|
| `Mutex` lock never resolves | Check that `unlock()` is always called (e.g., use `try/finally`). |
|
|
377
377
|
| `Serializer` tasks stop running | Did you call `close()`? Once closed, all new tasks fail immediately. |
|
|
378
378
|
| `Once` returns stale error even after retry | Ensure `retry: true` is set. Without it, a failure marks `_done = true` and never retries. |
|