@tanstack/pacer 0.13.0 → 0.15.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/dist/cjs/async-batcher.cjs +8 -0
- package/dist/cjs/async-batcher.cjs.map +1 -1
- package/dist/cjs/async-batcher.d.cts +8 -2
- package/dist/cjs/async-debouncer.cjs +17 -5
- package/dist/cjs/async-debouncer.cjs.map +1 -1
- package/dist/cjs/async-debouncer.d.cts +11 -1
- package/dist/cjs/async-queuer.cjs +14 -2
- package/dist/cjs/async-queuer.cjs.map +1 -1
- package/dist/cjs/async-queuer.d.cts +11 -1
- package/dist/cjs/async-rate-limiter.cjs +14 -2
- package/dist/cjs/async-rate-limiter.cjs.map +1 -1
- package/dist/cjs/async-rate-limiter.d.cts +11 -1
- package/dist/cjs/async-throttler.cjs +15 -3
- package/dist/cjs/async-throttler.cjs.map +1 -1
- package/dist/cjs/async-throttler.d.cts +11 -1
- package/dist/cjs/batcher.cjs +8 -0
- package/dist/cjs/batcher.cjs.map +1 -1
- package/dist/cjs/batcher.d.cts +8 -2
- package/dist/cjs/debouncer.cjs +15 -3
- package/dist/cjs/debouncer.cjs.map +1 -1
- package/dist/cjs/debouncer.d.cts +11 -1
- package/dist/cjs/event-client.cjs +18 -0
- package/dist/cjs/event-client.cjs.map +1 -0
- package/dist/cjs/event-client.d.cts +42 -0
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/queuer.cjs +13 -1
- package/dist/cjs/queuer.cjs.map +1 -1
- package/dist/cjs/queuer.d.cts +11 -1
- package/dist/cjs/rate-limiter.cjs +15 -3
- package/dist/cjs/rate-limiter.cjs.map +1 -1
- package/dist/cjs/rate-limiter.d.cts +11 -1
- package/dist/cjs/throttler.cjs +15 -3
- package/dist/cjs/throttler.cjs.map +1 -1
- package/dist/cjs/throttler.d.cts +11 -1
- package/dist/cjs/utils.cjs +10 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -0
- package/dist/esm/async-batcher.d.ts +8 -2
- package/dist/esm/async-batcher.js +9 -1
- package/dist/esm/async-batcher.js.map +1 -1
- package/dist/esm/async-debouncer.d.ts +11 -1
- package/dist/esm/async-debouncer.js +18 -6
- package/dist/esm/async-debouncer.js.map +1 -1
- package/dist/esm/async-queuer.d.ts +11 -1
- package/dist/esm/async-queuer.js +15 -3
- package/dist/esm/async-queuer.js.map +1 -1
- package/dist/esm/async-rate-limiter.d.ts +11 -1
- package/dist/esm/async-rate-limiter.js +15 -3
- package/dist/esm/async-rate-limiter.js.map +1 -1
- package/dist/esm/async-throttler.d.ts +11 -1
- package/dist/esm/async-throttler.js +16 -4
- package/dist/esm/async-throttler.js.map +1 -1
- package/dist/esm/batcher.d.ts +8 -2
- package/dist/esm/batcher.js +9 -1
- package/dist/esm/batcher.js.map +1 -1
- package/dist/esm/debouncer.d.ts +11 -1
- package/dist/esm/debouncer.js +16 -4
- package/dist/esm/debouncer.js.map +1 -1
- package/dist/esm/event-client.d.ts +42 -0
- package/dist/esm/event-client.js +18 -0
- package/dist/esm/event-client.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/queuer.d.ts +11 -1
- package/dist/esm/queuer.js +14 -2
- package/dist/esm/queuer.js.map +1 -1
- package/dist/esm/rate-limiter.d.ts +11 -1
- package/dist/esm/rate-limiter.js +16 -4
- package/dist/esm/rate-limiter.js.map +1 -1
- package/dist/esm/throttler.d.ts +11 -1
- package/dist/esm/throttler.js +16 -4
- package/dist/esm/throttler.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +10 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +12 -1
- package/src/async-batcher.ts +23 -3
- package/src/async-debouncer.ts +30 -7
- package/src/async-queuer.ts +29 -4
- package/src/async-rate-limiter.ts +28 -4
- package/src/async-throttler.ts +27 -5
- package/src/batcher.ts +18 -3
- package/src/debouncer.ts +30 -5
- package/src/event-client.ts +63 -0
- package/src/index.ts +2 -0
- package/src/queuer.ts +26 -2
- package/src/rate-limiter.ts +29 -5
- package/src/throttler.ts +29 -5
- package/src/utils.ts +15 -0
package/src/queuer.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { Store } from '@tanstack/store'
|
|
2
|
-
import { parseFunctionOrValue } from './utils'
|
|
2
|
+
import { createKey, parseFunctionOrValue } from './utils'
|
|
3
|
+
import { emitChange, pacerEventClient } from './event-client'
|
|
3
4
|
|
|
4
5
|
export interface QueuerState<TValue> {
|
|
6
|
+
/**
|
|
7
|
+
* Number of times addItem has been called (for reduction calculations)
|
|
8
|
+
*/
|
|
9
|
+
addItemCount: number
|
|
5
10
|
/**
|
|
6
11
|
* Number of items that have been processed by the queuer
|
|
7
12
|
*/
|
|
@@ -66,6 +71,7 @@ function getDefaultQueuerState<TValue>(): QueuerState<TValue> {
|
|
|
66
71
|
rejectionCount: 0,
|
|
67
72
|
size: 0,
|
|
68
73
|
status: 'idle',
|
|
74
|
+
addItemCount: 0,
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
|
|
@@ -108,6 +114,11 @@ export interface QueuerOptions<TValue> {
|
|
|
108
114
|
* Initial state for the queuer
|
|
109
115
|
*/
|
|
110
116
|
initialState?: Partial<QueuerState<TValue>>
|
|
117
|
+
/**
|
|
118
|
+
* Optional key to identify this queuer instance.
|
|
119
|
+
* If provided, the queuer will be identified by this key in the devtools and PacerProvider if applicable.
|
|
120
|
+
*/
|
|
121
|
+
key?: string
|
|
111
122
|
/**
|
|
112
123
|
* Maximum number of items allowed in the queuer
|
|
113
124
|
*/
|
|
@@ -148,6 +159,7 @@ const defaultOptions: Omit<
|
|
|
148
159
|
| 'onItemsChange'
|
|
149
160
|
| 'onReject'
|
|
150
161
|
| 'onExpire'
|
|
162
|
+
| 'key'
|
|
151
163
|
> = {
|
|
152
164
|
addItemsTo: 'back',
|
|
153
165
|
getItemsFrom: 'front',
|
|
@@ -244,13 +256,15 @@ export class Queuer<TValue> {
|
|
|
244
256
|
readonly store: Store<Readonly<QueuerState<TValue>>> = new Store(
|
|
245
257
|
getDefaultQueuerState<TValue>(),
|
|
246
258
|
)
|
|
259
|
+
key: string
|
|
247
260
|
options: QueuerOptions<TValue>
|
|
248
261
|
#timeoutId: NodeJS.Timeout | null = null
|
|
249
262
|
|
|
250
263
|
constructor(
|
|
251
|
-
|
|
264
|
+
public fn: (item: TValue) => void,
|
|
252
265
|
initialOptions: QueuerOptions<TValue> = {},
|
|
253
266
|
) {
|
|
267
|
+
this.key = createKey(initialOptions.key)
|
|
254
268
|
this.options = {
|
|
255
269
|
...defaultOptions,
|
|
256
270
|
...initialOptions,
|
|
@@ -273,6 +287,11 @@ export class Queuer<TValue> {
|
|
|
273
287
|
this.addItem(item, this.options.addItemsTo ?? 'back', isLast)
|
|
274
288
|
}
|
|
275
289
|
}
|
|
290
|
+
pacerEventClient.on('d-Queuer', (event) => {
|
|
291
|
+
if (event.payload.key !== this.key) return
|
|
292
|
+
this.#setState(event.payload.store.state)
|
|
293
|
+
this.setOptions(event.payload.options)
|
|
294
|
+
})
|
|
276
295
|
}
|
|
277
296
|
|
|
278
297
|
/**
|
|
@@ -307,6 +326,7 @@ export class Queuer<TValue> {
|
|
|
307
326
|
status,
|
|
308
327
|
}
|
|
309
328
|
})
|
|
329
|
+
emitChange('Queuer', this)
|
|
310
330
|
}
|
|
311
331
|
|
|
312
332
|
/**
|
|
@@ -366,6 +386,10 @@ export class Queuer<TValue> {
|
|
|
366
386
|
position: QueuePosition = this.options.addItemsTo ?? 'back',
|
|
367
387
|
runOnItemsChange: boolean = true,
|
|
368
388
|
): boolean => {
|
|
389
|
+
this.#setState({
|
|
390
|
+
addItemCount: this.store.state.addItemCount + 1,
|
|
391
|
+
})
|
|
392
|
+
|
|
369
393
|
if (this.store.state.items.length >= (this.options.maxSize ?? Infinity)) {
|
|
370
394
|
this.#setState({
|
|
371
395
|
rejectionCount: this.store.state.rejectionCount + 1,
|
package/src/rate-limiter.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Store } from '@tanstack/store'
|
|
2
|
-
import { parseFunctionOrValue } from './utils'
|
|
2
|
+
import { createKey, parseFunctionOrValue } from './utils'
|
|
3
|
+
import { emitChange, pacerEventClient } from './event-client'
|
|
3
4
|
import type { AnyFunction } from './types'
|
|
4
5
|
|
|
5
6
|
export interface RateLimiterState {
|
|
@@ -15,6 +16,10 @@ export interface RateLimiterState {
|
|
|
15
16
|
* Whether the rate limiter has exceeded the limit
|
|
16
17
|
*/
|
|
17
18
|
isExceeded: boolean
|
|
19
|
+
/**
|
|
20
|
+
* Number of times maybeExecute has been called (for reduction calculations)
|
|
21
|
+
*/
|
|
22
|
+
maybeExecuteCount: number
|
|
18
23
|
/**
|
|
19
24
|
* Number of function executions that have been rejected due to rate limiting
|
|
20
25
|
*/
|
|
@@ -26,13 +31,14 @@ export interface RateLimiterState {
|
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
function getDefaultRateLimiterState(): RateLimiterState {
|
|
29
|
-
return
|
|
34
|
+
return {
|
|
30
35
|
executionCount: 0,
|
|
31
36
|
executionTimes: [],
|
|
32
37
|
isExceeded: false,
|
|
33
38
|
rejectionCount: 0,
|
|
34
39
|
status: 'idle',
|
|
35
|
-
|
|
40
|
+
maybeExecuteCount: 0,
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
/**
|
|
@@ -48,6 +54,11 @@ export interface RateLimiterOptions<TFn extends AnyFunction> {
|
|
|
48
54
|
* Initial state for the rate limiter
|
|
49
55
|
*/
|
|
50
56
|
initialState?: Partial<RateLimiterState>
|
|
57
|
+
/**
|
|
58
|
+
* Optional key to identify this rate limiter instance.
|
|
59
|
+
* If provided, the rate limiter will be identified by this key in the devtools and PacerProvider if applicable.
|
|
60
|
+
*/
|
|
61
|
+
key?: string
|
|
51
62
|
/**
|
|
52
63
|
* Maximum number of executions allowed within the time window.
|
|
53
64
|
* Can be a number or a callback function that receives the rate limiter instance and returns a number.
|
|
@@ -77,7 +88,7 @@ export interface RateLimiterOptions<TFn extends AnyFunction> {
|
|
|
77
88
|
|
|
78
89
|
const defaultOptions: Omit<
|
|
79
90
|
Required<RateLimiterOptions<any>>,
|
|
80
|
-
'initialState' | 'onExecute' | 'onReject'
|
|
91
|
+
'initialState' | 'onExecute' | 'onReject' | 'key'
|
|
81
92
|
> = {
|
|
82
93
|
enabled: true,
|
|
83
94
|
limit: 1,
|
|
@@ -132,13 +143,15 @@ const defaultOptions: Omit<
|
|
|
132
143
|
export class RateLimiter<TFn extends AnyFunction> {
|
|
133
144
|
readonly store: Store<Readonly<RateLimiterState>> =
|
|
134
145
|
new Store<RateLimiterState>(getDefaultRateLimiterState())
|
|
146
|
+
key: string
|
|
135
147
|
options: RateLimiterOptions<TFn>
|
|
136
148
|
#timeoutIds: Set<NodeJS.Timeout> = new Set()
|
|
137
149
|
|
|
138
150
|
constructor(
|
|
139
|
-
|
|
151
|
+
public fn: TFn,
|
|
140
152
|
initialOptions: RateLimiterOptions<TFn>,
|
|
141
153
|
) {
|
|
154
|
+
this.key = createKey(initialOptions.key)
|
|
142
155
|
this.options = {
|
|
143
156
|
...defaultOptions,
|
|
144
157
|
...initialOptions,
|
|
@@ -147,6 +160,12 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
147
160
|
for (const executionTime of this.#getExecutionTimesInWindow()) {
|
|
148
161
|
this.#setCleanupTimeout(executionTime)
|
|
149
162
|
}
|
|
163
|
+
|
|
164
|
+
pacerEventClient.on('d-RateLimiter', (event) => {
|
|
165
|
+
if (event.payload.key !== this.key) return
|
|
166
|
+
this.#setState(event.payload.store.state)
|
|
167
|
+
this.setOptions(event.payload.options)
|
|
168
|
+
})
|
|
150
169
|
}
|
|
151
170
|
|
|
152
171
|
/**
|
|
@@ -174,6 +193,7 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
174
193
|
status,
|
|
175
194
|
}
|
|
176
195
|
})
|
|
196
|
+
emitChange('RateLimiter', this)
|
|
177
197
|
}
|
|
178
198
|
|
|
179
199
|
/**
|
|
@@ -213,6 +233,10 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
213
233
|
* ```
|
|
214
234
|
*/
|
|
215
235
|
maybeExecute = (...args: Parameters<TFn>): boolean => {
|
|
236
|
+
this.#setState({
|
|
237
|
+
maybeExecuteCount: this.store.state.maybeExecuteCount + 1,
|
|
238
|
+
})
|
|
239
|
+
|
|
216
240
|
this.#cleanupOldExecutions()
|
|
217
241
|
|
|
218
242
|
const relevantExecutionTimes = this.#getExecutionTimesInWindow()
|
package/src/throttler.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Store } from '@tanstack/store'
|
|
2
|
-
import { parseFunctionOrValue } from './utils'
|
|
2
|
+
import { createKey, parseFunctionOrValue } from './utils'
|
|
3
|
+
import { emitChange, pacerEventClient } from './event-client'
|
|
3
4
|
import type { AnyFunction } from './types'
|
|
4
5
|
|
|
5
6
|
export interface ThrottlerState<TFn extends AnyFunction> {
|
|
@@ -19,6 +20,10 @@ export interface ThrottlerState<TFn extends AnyFunction> {
|
|
|
19
20
|
* Timestamp of the last function execution in milliseconds
|
|
20
21
|
*/
|
|
21
22
|
lastExecutionTime: number
|
|
23
|
+
/**
|
|
24
|
+
* Number of times maybeExecute has been called (for reduction calculations)
|
|
25
|
+
*/
|
|
26
|
+
maybeExecuteCount: number
|
|
22
27
|
/**
|
|
23
28
|
* Timestamp when the next execution can occur in milliseconds
|
|
24
29
|
*/
|
|
@@ -32,14 +37,15 @@ export interface ThrottlerState<TFn extends AnyFunction> {
|
|
|
32
37
|
function getDefaultThrottlerState<
|
|
33
38
|
TFn extends AnyFunction,
|
|
34
39
|
>(): ThrottlerState<TFn> {
|
|
35
|
-
return
|
|
40
|
+
return {
|
|
36
41
|
executionCount: 0,
|
|
37
42
|
isPending: false,
|
|
38
43
|
lastArgs: undefined,
|
|
39
44
|
lastExecutionTime: 0,
|
|
40
45
|
nextExecutionTime: 0,
|
|
41
46
|
status: 'idle',
|
|
42
|
-
|
|
47
|
+
maybeExecuteCount: 0,
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
/**
|
|
@@ -56,6 +62,11 @@ export interface ThrottlerOptions<TFn extends AnyFunction> {
|
|
|
56
62
|
* Initial state for the throttler
|
|
57
63
|
*/
|
|
58
64
|
initialState?: Partial<ThrottlerState<TFn>>
|
|
65
|
+
/**
|
|
66
|
+
* A key to identify the throttler.
|
|
67
|
+
* If provided, the throttler will be identified by this key in the devtools and PacerProvider if applicable.
|
|
68
|
+
*/
|
|
69
|
+
key?: string
|
|
59
70
|
/**
|
|
60
71
|
* Whether to execute on the leading edge of the timeout.
|
|
61
72
|
* Defaults to true.
|
|
@@ -80,7 +91,7 @@ export interface ThrottlerOptions<TFn extends AnyFunction> {
|
|
|
80
91
|
|
|
81
92
|
const defaultOptions: Omit<
|
|
82
93
|
Required<ThrottlerOptions<any>>,
|
|
83
|
-
'initialState' | 'onExecute'
|
|
94
|
+
'initialState' | 'onExecute' | 'key'
|
|
84
95
|
> = {
|
|
85
96
|
enabled: true,
|
|
86
97
|
leading: true,
|
|
@@ -127,18 +138,26 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
127
138
|
readonly store: Store<Readonly<ThrottlerState<TFn>>> = new Store(
|
|
128
139
|
getDefaultThrottlerState(),
|
|
129
140
|
)
|
|
141
|
+
key: string | undefined
|
|
130
142
|
options: ThrottlerOptions<TFn>
|
|
131
143
|
#timeoutId: NodeJS.Timeout | undefined
|
|
132
144
|
|
|
133
145
|
constructor(
|
|
134
|
-
|
|
146
|
+
public fn: TFn,
|
|
135
147
|
initialOptions: ThrottlerOptions<TFn>,
|
|
136
148
|
) {
|
|
149
|
+
this.key = createKey(initialOptions.key)
|
|
137
150
|
this.options = {
|
|
138
151
|
...defaultOptions,
|
|
139
152
|
...initialOptions,
|
|
140
153
|
}
|
|
141
154
|
this.#setState(this.options.initialState ?? {})
|
|
155
|
+
|
|
156
|
+
pacerEventClient.on('d-Throttler', (event) => {
|
|
157
|
+
if (event.payload.key !== this.key) return
|
|
158
|
+
this.#setState(event.payload.store.state as ThrottlerState<TFn>)
|
|
159
|
+
this.setOptions(event.payload.options)
|
|
160
|
+
})
|
|
142
161
|
}
|
|
143
162
|
|
|
144
163
|
/**
|
|
@@ -169,6 +188,7 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
169
188
|
: 'idle',
|
|
170
189
|
}
|
|
171
190
|
})
|
|
191
|
+
emitChange('Throttler', this)
|
|
172
192
|
}
|
|
173
193
|
|
|
174
194
|
#getEnabled = (): boolean => {
|
|
@@ -202,6 +222,10 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
202
222
|
* ```
|
|
203
223
|
*/
|
|
204
224
|
maybeExecute = (...args: Parameters<TFn>): void => {
|
|
225
|
+
this.#setState({
|
|
226
|
+
maybeExecuteCount: this.store.state.maybeExecuteCount + 1,
|
|
227
|
+
})
|
|
228
|
+
|
|
205
229
|
const now = Date.now()
|
|
206
230
|
const timeSinceLastExecution = now - this.store.state.lastExecutionTime
|
|
207
231
|
const wait = this.#getWait()
|
package/src/utils.ts
CHANGED
|
@@ -10,3 +10,18 @@ export function parseFunctionOrValue<T, TArgs extends Array<any>>(
|
|
|
10
10
|
): T {
|
|
11
11
|
return isFunction(value) ? value(...args) : value
|
|
12
12
|
}
|
|
13
|
+
|
|
14
|
+
export function createKey(key?: string): string {
|
|
15
|
+
if (key) {
|
|
16
|
+
return key
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
typeof crypto !== 'undefined' &&
|
|
21
|
+
typeof crypto.randomUUID === 'function'
|
|
22
|
+
) {
|
|
23
|
+
return crypto.randomUUID()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return ''
|
|
27
|
+
}
|