async-queue-runner 1.0.1 → 1.0.2

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 (2) hide show
  1. package/README.md +171 -0
  2. package/package.json +14 -3
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # async-queue-runner
2
+
3
+ Library to run extendable async queues with branching, context mutation, and optional locking scopes.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install async-queue-runner
9
+ ```
10
+
11
+ ```sh
12
+ yarn add async-queue-runner
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { Action, QueueRunner, QueueContext } from 'async-queue-runner';
19
+
20
+ type Ctx = { value: number };
21
+
22
+ class Increment extends Action<Ctx> {
23
+ async execute({ value, extend }: Ctx & QueueContext): Promise<void> {
24
+ extend({ value: value + 1 });
25
+ }
26
+ }
27
+
28
+ class StopIfTooHigh extends Action<Ctx> {
29
+ async execute({ value, abort }: Ctx & QueueContext): Promise<void> {
30
+ if (value >= 3) abort();
31
+ }
32
+ }
33
+
34
+ const runner = new QueueRunner();
35
+ runner.add([Increment, Increment, StopIfTooHigh, Increment], { value: 0 });
36
+ ```
37
+
38
+ ## Core concepts
39
+
40
+ ### QueueAction
41
+
42
+ Queue items can be either:
43
+ - `IAction` instances (created actions), or
44
+ - `Action` classes (constructors).
45
+
46
+ ```ts
47
+ runner.add([
48
+ new Increment(),
49
+ Increment,
50
+ ]);
51
+ ```
52
+
53
+ Action classes are instantiated with no arguments. If you need constructor
54
+ options, pass an instance instead of a class.
55
+
56
+ ### QueueContext
57
+
58
+ Each action receives a context that can be extended at runtime.
59
+
60
+ ```ts
61
+ type QueueContext = {
62
+ push(actions: QueueAction[]): void
63
+ extend(obj: object): void
64
+ name(): string
65
+ abort(): void
66
+ }
67
+ ```
68
+
69
+ - `push` inserts new actions at the front of the remaining queue.
70
+ - `extend` merges new fields into the context.
71
+ - `name` returns the queue name.
72
+ - `abort` clears the remaining queue (preventive stop).
73
+
74
+ ### Error handling per action
75
+
76
+ Every action has `onError(error, context)`. The default implementation:
77
+ - logs to `context.logger.error(error)` when present, and
78
+ - calls `context.abort()` to stop the queue.
79
+
80
+ Override it to implement recovery:
81
+
82
+ ```ts
83
+ class Recoverable extends Action<{ recovered?: boolean }> {
84
+ async execute(): Promise<void> {
85
+ throw new Error('boom');
86
+ }
87
+
88
+ async onError(_error: Error, context: QueueContext): Promise<void> {
89
+ context.extend({ recovered: true });
90
+ }
91
+ }
92
+ ```
93
+
94
+ ## Locking
95
+
96
+ Locking ensures that actions with the same scope do not run at the same time across queues.
97
+
98
+ ### Define a locking action
99
+
100
+ ```ts
101
+ import { lockingClassFactory } from 'async-queue-runner';
102
+
103
+ class WithBrowserLock extends lockingClassFactory<{ url: string }>('browser') {
104
+ async execute({ url }: { url: string } & QueueContext): Promise<void> {
105
+ // protected by lock scope "browser"
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### Provide a lock manager
111
+
112
+ `QueueRunner` provides a shared lock manager automatically.
113
+ For direct `AsyncQueue` use, pass a `LockManager` instance.
114
+
115
+ ```ts
116
+ import { AsyncQueue, LockManager } from 'async-queue-runner';
117
+
118
+ const queue = new AsyncQueue({
119
+ name: 'q1',
120
+ actions: [WithBrowserLock],
121
+ lockingContext: new LockManager(),
122
+ });
123
+ ```
124
+
125
+ Lock scopes must be non-empty strings. Invalid scopes throw early.
126
+
127
+ ## Utilities
128
+
129
+ ```ts
130
+ import { util } from 'async-queue-runner';
131
+
132
+ // fixed delay
133
+ util.delay(500);
134
+
135
+ // branching
136
+ util.if<{ flag: boolean }>(
137
+ ({ flag }) => flag,
138
+ { then: [SomeAction], else: [OtherAction] }
139
+ );
140
+
141
+ // conditional actions
142
+ util.valid<{ count: number }>(
143
+ ({ count }) => count > 0,
144
+ [SomeAction]
145
+ );
146
+
147
+ // immediate abort action
148
+ util.abort;
149
+ ```
150
+
151
+ ## QueueRunner vs AsyncQueue
152
+
153
+ - `QueueRunner` manages multiple queues and shared locking.
154
+ - `AsyncQueue` runs a single queue directly.
155
+
156
+ ```ts
157
+ import { QueueRunner } from 'async-queue-runner';
158
+
159
+ const runner = new QueueRunner();
160
+ runner.add([SomeAction], { initial: true }, 'my-queue');
161
+ ```
162
+
163
+ ## Logging
164
+
165
+ `AsyncQueue` accepts a logger for queue-level logs.
166
+ Default `onError` uses `context.logger.error` if available in context.
167
+
168
+ ```ts
169
+ const runner = new QueueRunner({ logger: myQueueLogger });
170
+ runner.add([SomeAction], { logger: myActionLogger });
171
+ ```
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "async-queue-runner",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Library to run in parallel extendable queue of tasks",
5
5
  "scripts": {
6
6
  "compile": "tsc --project ./tsconfig.json",
7
- "copy:package:json": "copyfiles ./package.json ./built/ && copyfiles ./_esm/* ./built && copyfiles ./_cjs/* ./built",
7
+ "copy:package:json": "copyfiles ./package.json ./README.md ./built/ && copyfiles ./_esm/* ./built && copyfiles ./_cjs/* ./built",
8
8
  "build:all": "tsc -p ./tsconfig.esm.json && tsc -p ./tsconfig.cjs.json && tsc -p ./tsconfig.types.json",
9
9
  "build": "del-cli ./built/ && npm run build:all && npm run copy:package:json",
10
10
  "bump": "npm version minor",
@@ -22,7 +22,18 @@
22
22
  }
23
23
  },
24
24
  "types": "./_types/index.d.ts",
25
- "keywords": [],
25
+ "keywords": [
26
+ "async",
27
+ "queue",
28
+ "task-queue",
29
+ "runner",
30
+ "workflow",
31
+ "jobs",
32
+ "locking",
33
+ "actions",
34
+ "typescript",
35
+ "node"
36
+ ],
26
37
  "author": "Eugeny Dementev",
27
38
  "license": "MIT",
28
39
  "devDependencies": {