time-queues 1.2.4 → 1.3.1

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.
Files changed (49) hide show
  1. package/README.md +117 -36
  2. package/llms-full.txt +430 -0
  3. package/llms.txt +95 -0
  4. package/package.json +43 -12
  5. package/src/CancelTaskError.d.ts +2 -1
  6. package/src/CancelTaskError.js +2 -4
  7. package/src/Counter.d.ts +0 -1
  8. package/src/Counter.js +0 -2
  9. package/src/FrameQueue.d.ts +2 -2
  10. package/src/FrameQueue.js +0 -2
  11. package/src/IdleQueue.d.ts +2 -2
  12. package/src/IdleQueue.js +0 -2
  13. package/src/LimitedQueue.d.ts +104 -0
  14. package/src/LimitedQueue.js +78 -0
  15. package/src/ListQueue.d.ts +1 -6
  16. package/src/ListQueue.js +18 -3
  17. package/src/MicroTask.d.ts +7 -1
  18. package/src/MicroTask.js +47 -15
  19. package/src/MicroTaskQueue.d.ts +24 -20
  20. package/src/MicroTaskQueue.js +22 -7
  21. package/src/PageWatcher.d.ts +2 -2
  22. package/src/PageWatcher.js +0 -2
  23. package/src/Retainer.d.ts +4 -4
  24. package/src/Retainer.js +0 -2
  25. package/src/Scheduler.d.ts +23 -17
  26. package/src/Scheduler.js +1 -2
  27. package/src/Throttler.d.ts +7 -2
  28. package/src/Throttler.js +1 -2
  29. package/src/audit.js +0 -2
  30. package/src/batch.d.ts +16 -0
  31. package/src/batch.js +40 -0
  32. package/src/debounce.js +0 -2
  33. package/src/defer.d.ts +3 -4
  34. package/src/defer.js +0 -2
  35. package/src/index.d.ts +7 -2
  36. package/src/random-dist.d.ts +31 -0
  37. package/src/random-dist.js +27 -0
  38. package/src/random-sleep.d.ts +57 -0
  39. package/src/random-sleep.js +27 -0
  40. package/src/sample.d.ts +1 -1
  41. package/src/sample.js +0 -2
  42. package/src/sleep.d.ts +1 -1
  43. package/src/sleep.js +0 -2
  44. package/src/throttle.d.ts +2 -1
  45. package/src/throttle.js +0 -2
  46. package/src/when-dom-loaded.d.ts +4 -8
  47. package/src/when-dom-loaded.js +3 -9
  48. package/src/when-loaded.d.ts +4 -8
  49. package/src/when-loaded.js +3 -9
@@ -2,68 +2,72 @@ import MicroTask from './MicroTask';
2
2
 
3
3
  /**
4
4
  * A queue of microtasks that will be executed when scheduled.
5
- * It is a base class for other task queues.
5
+ * It serves as a base class for other task queues.
6
6
  */
7
7
  export declare class MicroTaskQueue {
8
8
  /**
9
- * Whether the queue is paused.
9
+ * Whether the queue is currently paused.
10
+ * When paused, new tasks are queued but not executed immediately.
10
11
  */
11
12
  paused: boolean;
12
13
 
13
14
  /**
14
15
  * Creates a new microtask queue.
15
- * @param paused Whether the queue should start paused.
16
+ * @param paused Whether the queue should start in a paused state.
16
17
  */
17
18
  constructor(paused?: boolean);
18
19
 
19
20
  /**
20
21
  * Whether the queue is empty.
21
- * It is meant to be overridden in subclasses.
22
+ * This property should be overridden in subclasses to provide actual implementation.
22
23
  */
23
24
  get isEmpty(): boolean;
24
25
 
25
26
  /**
26
- * Enqueues a microtask.
27
- * It is meant to be overridden in subclasses.
27
+ * Enqueues a microtask for execution.
28
+ * This method should be overridden in subclasses to provide actual implementation.
28
29
  * @param fn The function to execute when the microtask is scheduled.
29
30
  * @returns The enqueued microtask.
30
31
  */
31
32
  enqueue(fn: () => unknown): MicroTask;
32
33
 
33
34
  /**
34
- * Dequeues a microtask.
35
- * It is meant to be overridden in subclasses.
35
+ * Dequeues a microtask from the queue.
36
+ * This method should be overridden in subclasses to provide actual implementation.
36
37
  * @param task The microtask to dequeue.
37
- * @returns The queue.
38
+ * @returns The queue instance for chaining.
38
39
  */
39
40
  dequeue(task: MicroTask): this;
40
41
 
41
42
  /**
42
- * Schedules a microtask with a promise.
43
- * It can be overridden in subclasses, if more arguments are needed.
44
- * @param fn The function to execute when the microtask is scheduled, it can be an async function.
43
+ * Schedules a microtask with a promise for execution.
44
+ * This can be overridden in subclasses if more arguments are needed.
45
+ * @param fn The function to execute when the microtask is scheduled. It can be an async function.
46
+ * @param args Additional arguments to pass to `enqueue()`. They are there to accommodate custom implementations in subclasses.
45
47
  * @returns The scheduled microtask.
46
48
  */
47
- schedule(fn: (() => unknown) | null | undefined): MicroTask;
49
+ schedule(fn: (() => unknown) | null | undefined, ...args: unknown[]): MicroTask;
48
50
 
49
51
  /**
50
- * Clears the queue.
51
- * It is meant to be overridden in subclasses.
52
- * @returns The queue.
52
+ * Clears all tasks from the queue.
53
+ * This method should be overridden in subclasses to provide actual implementation.
54
+ * @returns The queue instance for chaining.
53
55
  */
54
56
  clear(): this;
55
57
 
56
58
  /**
57
59
  * Pauses the queue.
58
- * It is meant to be overridden in subclasses.
59
- * @returns The queue.
60
+ * When paused, new tasks are queued but not executed immediately.
61
+ * This method should be overridden in subclasses to provide actual implementation.
62
+ * @returns The queue instance for chaining.
60
63
  */
61
64
  pause(): this;
62
65
 
63
66
  /**
64
67
  * Resumes the queue.
65
- * It is meant to be overridden in subclasses.
66
- * @returns The queue.
68
+ * When resumed, queued tasks will be executed according to their scheduling.
69
+ * This method should be overridden in subclasses to provide actual implementation.
70
+ * @returns The queue instance for chaining.
67
71
  */
68
72
  resume(): this;
69
73
  }
@@ -1,14 +1,19 @@
1
1
  // @ts-self-types="./MicroTaskQueue.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  import MicroTask from './MicroTask.js';
6
4
 
5
+ /**
6
+ * Base queue class for managing task lifecycle.
7
+ * AI-NOTE: This is an abstract base class - concrete implementations should extend
8
+ * ListQueue for actual task storage and processing.
9
+ * @see ListQueue - The primary class for queue implementations
10
+ */
7
11
  export class MicroTaskQueue {
8
12
  constructor(paused) {
9
13
  this.paused = Boolean(paused);
10
14
  }
11
15
  // API to be overridden in subclasses
16
+ // AI-NOTE: Base implementation returns true - subclasses override with actual logic
12
17
  get isEmpty() {
13
18
  return true;
14
19
  }
@@ -20,6 +25,11 @@ export class MicroTaskQueue {
20
25
  this.paused = false;
21
26
  return this;
22
27
  }
28
+ /**
29
+ * Enqueue a function for execution.
30
+ * AI-NOTE: Creates MicroTask but does NOT create promise automatically.
31
+ * Call task.makePromise() if promise access is needed.
32
+ */
23
33
  enqueue(fn) {
24
34
  const task = new MicroTask(fn);
25
35
  return task;
@@ -31,21 +41,26 @@ export class MicroTaskQueue {
31
41
  clear() {
32
42
  return this;
33
43
  }
34
- // Generic API
44
+ /**
45
+ * Schedule a function with automatic promise creation.
46
+ * AI-NOTE: This is the convenience method - it calls both enqueue() and makePromise().
47
+ * Returns a MicroTask with an active promise.
48
+ */
35
49
  schedule(fn, ...args) {
36
50
  fn ||= MicroTaskQueue.returnArgs;
37
51
  const task = this.enqueue(
38
- (...args) => {
52
+ function (...args) {
53
+ this.makePromise();
39
54
  try {
40
- task.resolve(fn(...args));
55
+ this.resolve(fn(...args));
41
56
  } catch (error) {
42
- task.cancel();
57
+ this.cancel(error);
43
58
  }
59
+ return this.promise;
44
60
  },
45
61
  ...args
46
62
  );
47
63
  task.makePromise();
48
- task.fn = fn;
49
64
  return task;
50
65
  }
51
66
  static returnArgs(...args) {
@@ -33,7 +33,7 @@ export declare class PageWatcher extends ListQueue {
33
33
  /**
34
34
  * Enqueues a task.
35
35
  * @param fn The function to execute.
36
- * @param initialize Whether the function should be executed before the state changes.
36
+ * @param initialize Whether the function should be called immediately with the current state.
37
37
  * @returns The task object.
38
38
  */
39
39
  enqueue(
@@ -90,4 +90,4 @@ export declare const watchStates: (
90
90
  */
91
91
  export declare const pageWatcher: PageWatcher;
92
92
 
93
- export default PageWatcher;
93
+ export default pageWatcher;
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./PageWatcher.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  import ListQueue from './ListQueue.js';
6
4
 
7
5
  // Based on information from https://developer.chrome.com/docs/web-platform/page-lifecycle-api
package/src/Retainer.d.ts CHANGED
@@ -13,7 +13,7 @@ export declare interface RetainerOptions<T = unknown> {
13
13
  /**
14
14
  * The retention period in milliseconds.
15
15
  */
16
- retentionPeriod: number;
16
+ retentionPeriod?: number;
17
17
  }
18
18
 
19
19
  /**
@@ -55,14 +55,14 @@ export declare class Retainer<T = unknown> implements RetainerOptions<T> {
55
55
  * Retrieves the retained value.
56
56
  * @returns The retained value as a promise.
57
57
  */
58
- async get(): Promise<T>;
58
+ get(): Promise<T>;
59
59
 
60
60
  /**
61
61
  * Releases the retained value.
62
- * @param immediately Whether to release the value immediately. Otherwise it'll be retained for the retention period.
62
+ * @param immediately Whether to release the value immediately. Otherwise, it will be retained for the retention period.
63
63
  * @returns The retainer object.
64
64
  */
65
- async release(immediately?: boolean): Promise<this>;
65
+ release(immediately?: boolean): Promise<this>;
66
66
  }
67
67
 
68
68
  export default Retainer;
package/src/Retainer.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./Retainer.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  export class Retainer {
6
4
  constructor({create, destroy, retentionPeriod = 1_000}) {
7
5
  if (!create || !destroy) throw new Error('Retainer: create and destroy are required');
@@ -55,10 +55,10 @@ export declare class Task extends MicroTask {
55
55
  /**
56
56
  * Cancels the microtask, if a promise is created.
57
57
  * If the microtask is canceled, the promise will be rejected with a CancelTaskError.
58
- * It can be overridden in subclasses.
58
+ * @param error The optional error to use as the cause of the cancellation.
59
59
  * @returns The microtask.
60
60
  */
61
- cancel(): this;
61
+ cancel(error?: Error): this;
62
62
  }
63
63
 
64
64
  /**
@@ -67,51 +67,55 @@ export declare class Task extends MicroTask {
67
67
  export declare class Scheduler extends MicroTaskQueue {
68
68
  /**
69
69
  * Whether the scheduler is paused.
70
+ * When paused, new tasks are queued but not executed immediately.
70
71
  */
71
72
  paused: boolean;
72
73
 
73
74
  /**
74
- * The tolerance for comparing starting time of tasks.
75
+ * The tolerance for comparing starting times of tasks.
76
+ * This allows for small timing differences in task execution.
75
77
  */
76
78
  tolerance: number;
77
79
 
78
80
  /**
79
81
  * Creates a new scheduler.
80
- * @param paused Whether the scheduler should start paused.
81
- * @param tolerance The tolerance for comparing starting time of tasks.
82
+ * @param paused Whether the scheduler should start in a paused state.
83
+ * @param tolerance The tolerance for comparing starting times of tasks (default is 4ms).
82
84
  */
83
- constructor(paused?: boolean, tolerance: number = 4);
85
+ constructor(paused?: boolean, tolerance?: number);
84
86
 
85
87
  /**
86
88
  * Whether the scheduler is empty.
89
+ * Returns true if there are no tasks scheduled for execution.
87
90
  */
88
91
  get isEmpty(): boolean;
89
92
 
90
93
  /**
91
94
  * The next scheduled time or `Infinity` if the scheduler is empty.
95
+ * Represents the time when the next task is scheduled to execute.
92
96
  */
93
97
  get nextTime(): number;
94
98
 
95
99
  /**
96
- * Enqueues a task.
100
+ * Enqueues a task for future execution.
97
101
  * @param fn The function to execute.
98
102
  * @param delay The delay before the task is executed. It can be a number of milliseconds or a `Date` object as an absolute time.
99
- * @returns The task object.
103
+ * @returns The task object that was enqueued.
100
104
  */
101
105
  enqueue(fn: ({task: Task, scheduler: Scheduler}) => unknown, delay: number | Date): Task;
102
106
 
103
107
  /**
104
108
  * Removes a task from the scheduler.
105
109
  * @param task The task to remove.
106
- * @returns The scheduler object.
110
+ * @returns The scheduler object for chaining.
107
111
  */
108
112
  dequeue(task: Task): this;
109
113
 
110
114
  /**
111
115
  * Schedules a task to run in the future.
112
- * @param fn The function to execute. If `undefined` or `null`, the task's promise will be resolved with function's arguments. Otherwise, it is resolved with the function's return value.
116
+ * @param fn The function to execute. If `undefined` or `null`, the task's promise will be resolved with the function's arguments. Otherwise, it is resolved with the function's return value.
113
117
  * @param delay The delay before the task is executed. It can be a number of milliseconds or a `Date` object as an absolute time.
114
- * @returns The task object.
118
+ * @returns The task object that was scheduled.
115
119
  */
116
120
  schedule(
117
121
  fn: (({task: Task, scheduler: Scheduler}) => unknown) | null | undefined,
@@ -119,20 +123,22 @@ export declare class Scheduler extends MicroTaskQueue {
119
123
  ): Task;
120
124
 
121
125
  /**
122
- * Clears the queue.
123
- * @returns The queue.
126
+ * Clears all tasks from the scheduler.
127
+ * @returns The scheduler instance for chaining.
124
128
  */
125
129
  clear(): this;
126
130
 
127
131
  /**
128
- * Pauses the queue.
129
- * @returns The queue.
132
+ * Pauses the scheduler.
133
+ * When paused, new tasks are queued but not executed immediately.
134
+ * @returns The scheduler instance for chaining.
130
135
  */
131
136
  pause(): this;
132
137
 
133
138
  /**
134
- * Resumes the queue.
135
- * @returns The queue.
139
+ * Resumes the scheduler.
140
+ * When resumed, queued tasks will be executed according to their scheduling.
141
+ * @returns The scheduler instance for chaining.
136
142
  */
137
143
  resume(): this;
138
144
  }
package/src/Scheduler.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./Scheduler.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  import MinHeap from 'list-toolkit/heap.js';
6
4
  import MicroTask from './MicroTask.js';
7
5
  import MicroTaskQueue from './MicroTaskQueue.js';
@@ -90,6 +88,7 @@ export class Scheduler extends MicroTaskQueue {
90
88
  this.queue.array.forEach(task => task.cancel());
91
89
  this.queue.clear();
92
90
  if (!paused) this.resume();
91
+ return this;
93
92
  }
94
93
 
95
94
  startQueue() {
@@ -71,6 +71,11 @@ export declare class Throttler implements ThrottlerOptions {
71
71
  */
72
72
  wait(key: unknown): Promise<void>;
73
73
 
74
+ /**
75
+ * Removes expired keys from the last seen map.
76
+ */
77
+ vacuum(): void;
78
+
74
79
  /**
75
80
  * Retrieves the vacuuming state.
76
81
  * @returns `true` if the vacuuming is active, `false` otherwise.
@@ -79,14 +84,14 @@ export declare class Throttler implements ThrottlerOptions {
79
84
 
80
85
  /**
81
86
  * Starts the vacuum process.
82
- * The vacuum process removes keys that expired.
87
+ * The vacuum process removes expired keys.
83
88
  * @returns The throttler object.
84
89
  */
85
90
  startVacuum(): this;
86
91
 
87
92
  /**
88
93
  * Stops the vacuum process.
89
- * The vacuum process removes keys that expired.
94
+ * The vacuum process removes expired keys.
90
95
  * @returns The throttler object.
91
96
  */
92
97
  stopVacuum(): this;
package/src/Throttler.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./Throttler.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  import sleep from './sleep.js';
6
4
 
7
5
  export class Throttler {
@@ -57,6 +55,7 @@ export class Throttler {
57
55
  this.handle = setInterval(() => {
58
56
  this.vacuum();
59
57
  }, this.vacuumPeriod);
58
+ if (this.handle.unref) this.handle.unref();
60
59
  return this;
61
60
  }
62
61
 
package/src/audit.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./audit.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  export const audit = (fn, ms) => {
6
4
  let handle = null,
7
5
  lastSeenArgs = null;
package/src/batch.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Runs asynchronous operations in parallel, no more than a specified number at a time.
3
+ * It takes an array of functions, which return promises when invoked without arguments.
4
+ * All other non-function values are passed as-is and promises are resolved.
5
+ * Modeled after Promise.all().
6
+ *
7
+ * @param fns An array of parameterless functions (asynchronous or not), promises, or values
8
+ * @param limit How many asynchronous operations to run in parallel (default is 4)
9
+ * @returns A promise that resolves when all functions have completed to an array of results
10
+ */
11
+ export declare function batch(
12
+ fns: ((() => PromiseLike<unknown>) | PromiseLike<unknown> | unknown)[],
13
+ limit?: number
14
+ ): Promise<unknown[]>;
15
+
16
+ export default batch;
package/src/batch.js ADDED
@@ -0,0 +1,40 @@
1
+ // @ts-self-types="./batch.d.ts"
2
+
3
+ const wrap = value => {
4
+ if (typeof value == 'function') return Promise.resolve(value());
5
+ if (value && typeof value.then == 'function') return value; // thenable
6
+ return Promise.resolve(value);
7
+ };
8
+
9
+ export const batch = (fns, limit = 4) => {
10
+ if (!fns.length) return Promise.resolve([]);
11
+ if (limit < 1) limit = 1;
12
+
13
+ const result = [];
14
+ let next = limit,
15
+ available = limit;
16
+
17
+ const saveResult = (index, resolve, reject) => value => {
18
+ result[index] = value;
19
+ if (next < fns.length) {
20
+ wrap(fns[next]).then(saveResult(next, resolve, reject), reject);
21
+ ++next;
22
+ } else {
23
+ ++available;
24
+ if (available === limit) {
25
+ // we are done
26
+ resolve(result);
27
+ }
28
+ }
29
+ };
30
+
31
+ return new Promise((resolve, reject) => {
32
+ // start the pump
33
+ for (let i = 0, n = Math.min(fns.length, limit); i < n; ++i) {
34
+ wrap(fns[i]).then(saveResult(i, resolve, reject), reject);
35
+ --available;
36
+ }
37
+ });
38
+ };
39
+
40
+ export default batch;
package/src/debounce.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./debounce.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  export const debounce = (fn, ms) => {
6
4
  let handle = null;
7
5
  return (...args) => {
package/src/defer.d.ts CHANGED
@@ -6,12 +6,11 @@
6
6
  * - `setTimeout()`
7
7
  *
8
8
  * @param fn The function to delay.
9
- * @returns A function that, when called, will execute the provided function.
10
9
  */
11
- export declare function defer<A extends unknown[]>(fn: (...args: A) => void): (...args: A) => void;
10
+ export declare function defer(fn: () => void): void;
12
11
 
13
12
  /**
14
- * Schedules a function to be called when the next available time.
13
+ * Schedules a function to be called at the next available time.
15
14
  *
16
15
  * @param fn The function to schedule.
17
16
  * @returns A promise that resolves when the function is called.
@@ -19,7 +18,7 @@ export declare function defer<A extends unknown[]>(fn: (...args: A) => void): (.
19
18
  export declare function scheduleDefer<R extends unknown>(fn: () => R): Promise<Awaited<R>>;
20
19
 
21
20
  /**
22
- * Schedules a function to be called when the next available time.
21
+ * Schedules a function to be called at the next available time.
23
22
  *
24
23
  * @param fn The function to schedule.
25
24
  * @returns A promise that resolves when the function is called.
package/src/defer.js CHANGED
@@ -1,7 +1,5 @@
1
1
  // @ts-self-types="./defer.d.ts"
2
2
 
3
- 'use strict';
4
-
5
3
  let deferImplementation = setTimeout;
6
4
 
7
5
  if (typeof requestIdleCallback == 'function') {
package/src/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  declare module 'time-queues' {
2
2
  export * from './audit';
3
+ export * from './batch';
3
4
  export * from './debounce';
4
5
  export * from './defer';
5
6
  export * from './sample';
@@ -9,15 +10,19 @@ declare module 'time-queues' {
9
10
  export * from './CancelTaskError';
10
11
  export * from './MicroTask';
11
12
  export * from './MicroTaskQueue';
13
+ export * from './LimitedQueue';
12
14
  export * from './ListQueue';
13
15
  export * from './FrameQueue';
14
16
  export * from './IdleQueue';
15
17
 
18
+ export * from './Counter';
16
19
  export * from './PageWatcher';
17
- export * from './Scheduler';
18
20
  export * from './Retainer';
21
+ export * from './Scheduler';
19
22
  export * from './Throttler';
20
- export * from './Counter';
23
+
24
+ export * from './random-dist';
25
+ export * from './random-sleep';
21
26
 
22
27
  export * from './when-dom-loaded';
23
28
  export * from './when-loaded';
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Generate a random number from a uniform distribution.
3
+ * @param min The minimum value of the distribution.
4
+ * @param max The maximum value of the distribution.
5
+ * @returns A random number from the uniform distribution.
6
+ */
7
+ export declare function uniform(min: number, max: number): number;
8
+
9
+ /**
10
+ * Generate a random number from a normal distribution.
11
+ * @param mean The mean of the distribution.
12
+ * @param stdDev The standard deviation of the distribution.
13
+ * @param skewness The skewness of the distribution.
14
+ * @returns A random number from the normal distribution.
15
+ */
16
+ export declare function normal(mean: number, stdDev: number, skewness: number = 0): number;
17
+
18
+ /**
19
+ * Generate a random number from an exponential distribution.
20
+ * @param lambda The rate parameter of the distribution.
21
+ * @returns A random number from the exponential distribution.
22
+ */
23
+ export declare function expo(lambda: number): number;
24
+
25
+ /**
26
+ * Generate a random number from a Pareto distribution.
27
+ * @param min The minimum value of the distribution.
28
+ * @param alpha The shape parameter of the distribution.
29
+ * @returns A random number from the Pareto distribution.
30
+ */
31
+ export declare function pareto(min: number, alpha: number): number;
@@ -0,0 +1,27 @@
1
+ // @ts-self-types="./random-dist.d.ts"
2
+
3
+ export const uniform = (min, max) => {
4
+ const range = Math.abs(max - min);
5
+ return Math.random() * range + Math.min(min, max);
6
+ };
7
+
8
+ export const normal = (mean, stdDev, skewness = 0) => {
9
+ let u = 0,
10
+ v = 0;
11
+ while (!u) u = Math.random(); // Converting [0,1) to (0,1)
12
+ while (!v) v = Math.random();
13
+ let z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
14
+ if (!skewness) return z * stdDev + mean;
15
+ const delta = skewness / Math.sqrt(1 + skewness * skewness),
16
+ x = delta * z + Math.sqrt(1 - delta * delta) * v;
17
+ z = z >= 0 ? x : -x;
18
+ return z * stdDev + mean;
19
+ };
20
+
21
+ export const expo = lambda => {
22
+ return -Math.log(1 - Math.random()) / lambda;
23
+ };
24
+
25
+ export const pareto = (min, alpha) => {
26
+ return min / Math.pow(1 - Math.random(), 1 / alpha);
27
+ };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Random sleep function modeled after `sleep()`.
3
+ */
4
+ export type RandomSleepFunction = () => Promise<void>;
5
+
6
+ /**
7
+ * Creates a random sleep function that uses a uniform distribution.
8
+ * @param min The minimum delay in milliseconds.
9
+ * @param max The maximum delay in milliseconds.
10
+ * @returns A sleep function.
11
+ */
12
+ export declare function randomUniformSleep(min: number, max: number): RandomSleepFunction;
13
+
14
+ /**
15
+ * Creates a random sleep function that uses a normal distribution.
16
+ * @param mean The mean delay in milliseconds.
17
+ * @param stdDev The standard deviation of the delay in milliseconds.
18
+ * @param skewness The skewness of the delay distribution.
19
+ * @returns A sleep function.
20
+ */
21
+ export declare function randomNormalSleep(
22
+ mean: number,
23
+ stdDev: number,
24
+ skewness: number = 0
25
+ ): RandomSleepFunction;
26
+
27
+ /**
28
+ * Creates a random sleep function that uses an exponential distribution.
29
+ * @param rate The rate parameter of the exponential distribution (how many times per `range` an event occurs).
30
+ * @param range The range of the exponential distribution.
31
+ * @param base The base of the exponential distribution.
32
+ * @returns A sleep function.
33
+ */
34
+ export declare function randomExpoSleep(
35
+ rate: number,
36
+ range: number,
37
+ base: number = 0
38
+ ): RandomSleepFunction;
39
+
40
+ /**
41
+ * Creates a random sleep function that uses a Pareto distribution.
42
+ * @param min The minimum delay in milliseconds.
43
+ * @param ratio The ratio of the Pareto distribution, e.g., 0.8 for the 80/20 Pareto rule. Should be a value between 0.5 and 1.
44
+ * @returns A sleep function.
45
+ * @throws Error if the ratio is not between 0.5 and 1.
46
+ */
47
+ export declare function randomParetoSleep(min: number, ratio: number = 0.8): RandomSleepFunction;
48
+
49
+ /**
50
+ * A simple sleep function that uses a uniform distribution.
51
+ * @param max The maximum delay in milliseconds.
52
+ * @param min The minimum delay in milliseconds.
53
+ * @returns A promise that resolves after the delay.
54
+ */
55
+ export declare function randomSleep(max: number, min: number = 0): Promise<void>;
56
+
57
+ export default randomSleep;
@@ -0,0 +1,27 @@
1
+ // @ts-self-types="./random-sleep.d.ts"
2
+
3
+ import sleep from './sleep.js';
4
+ import {uniform, normal, expo, pareto} from './random-dist.js';
5
+
6
+ export const randomUniformSleep = (min, max) => () => sleep(uniform(min, max));
7
+
8
+ export const randomNormalSleep =
9
+ (mean, stdDev, skewness = 0) =>
10
+ () =>
11
+ sleep(normal(mean, stdDev, skewness));
12
+
13
+ export const randomExpoSleep =
14
+ (rate, range, base = 0) =>
15
+ () =>
16
+ sleep(range * expo(rate) + base);
17
+
18
+ export const randomParetoSleep = (min, ratio = 0.8) => {
19
+ if (ratio <= 0.5 || ratio >= 1 || isNaN(ratio))
20
+ throw new Error('ratio must be greater than 0.5 and less than 1');
21
+ const alpha = 1 / (1 - Math.log(ratio) / Math.log(1 - ratio));
22
+ return () => sleep(pareto(min, alpha));
23
+ };
24
+
25
+ export const randomSleep = (max, min = 0) => sleep(uniform(min, max));
26
+
27
+ export default randomSleep;