0
# Progress Tracking
1
2
Real-time progress monitoring with task lifecycle callbacks and comprehensive statistics for monitoring promise pool execution and building progress indicators.
3
4
## Capabilities
5
6
### Task Lifecycle Callbacks
7
8
Register callbacks to be notified when tasks start and finish processing.
9
10
```typescript { .api }
11
/**
12
* Register a callback to be called when a task starts processing
13
* @param handler - Callback function receiving item and pool instance
14
* @returns PromisePool instance for chaining
15
*/
16
onTaskStarted(handler: OnProgressCallback<T>): PromisePool<T>;
17
18
/**
19
* Register a callback to be called when a task finishes processing
20
* @param handler - Callback function receiving item and pool instance
21
* @returns PromisePool instance for chaining
22
*/
23
onTaskFinished(handler: OnProgressCallback<T>): PromisePool<T>;
24
25
type OnProgressCallback<T> = (
26
item: T,
27
pool: Stoppable & Statistics<T> & UsesConcurrency
28
) => void;
29
```
30
31
**Key Features:**
32
- Multiple callbacks can be registered by chaining calls
33
- Callbacks receive the current item and pool instance with statistics
34
- Callbacks are called synchronously during task lifecycle events
35
- Access to real-time pool statistics within callbacks
36
37
**Usage Examples:**
38
39
```typescript
40
import { PromisePool } from "@supercharge/promise-pool";
41
42
// Basic progress tracking
43
await PromisePool
44
.for(users)
45
.onTaskStarted((item, pool) => {
46
console.log(`Started processing: ${item.name}`);
47
console.log(`Progress: ${pool.processedPercentage().toFixed(1)}%`);
48
console.log(`Active tasks: ${pool.activeTasksCount()}/${pool.concurrency()}`);
49
})
50
.onTaskFinished((item, pool) => {
51
console.log(`Finished processing: ${item.name}`);
52
console.log(`Completed: ${pool.processedCount()} items`);
53
})
54
.process(async (user) => await processUser(user));
55
56
// Multiple progress handlers
57
await PromisePool
58
.for(items)
59
.onTaskStarted((item, pool) => {
60
// Handler 1: Update progress bar
61
updateProgressBar(pool.processedPercentage());
62
})
63
.onTaskStarted((item, pool) => {
64
// Handler 2: Log to console
65
console.log(`Processing ${item.id}...`);
66
})
67
.onTaskFinished((item, pool) => {
68
// Handler 1: Update status
69
updateStatus(`Processed ${pool.processedCount()} items`);
70
})
71
.onTaskFinished((item, pool) => {
72
// Handler 2: Track metrics
73
trackMetrics(item, pool);
74
})
75
.process(async (item) => processItem(item));
76
```
77
78
### Statistics Interface
79
80
Access real-time statistics about pool execution state.
81
82
```typescript { .api }
83
/**
84
* Interface providing pool execution statistics
85
*/
86
interface Statistics<T> {
87
/** Returns the number of currently active tasks */
88
activeTasksCount(): number;
89
90
/** Returns the number of currently active tasks (deprecated - use activeTasksCount) */
91
activeTaskCount(): number;
92
93
/** Returns the list of processed items */
94
processedItems(): T[];
95
96
/** Returns the number of processed items */
97
processedCount(): number;
98
99
/** Returns the percentage progress of items that have been processed */
100
processedPercentage(): number;
101
}
102
```
103
104
**Usage Examples:**
105
106
```typescript
107
// Progress monitoring during task execution
108
await PromisePool
109
.for(largeDataSet)
110
.onTaskStarted((item, pool) => {
111
const stats = {
112
activeCount: pool.activeTasksCount(),
113
processedCount: pool.processedCount(),
114
processedPercentage: pool.processedPercentage(),
115
totalProcessed: pool.processedItems().length
116
};
117
118
console.log(`Pool Stats:`, stats);
119
})
120
.process(async (item) => processItem(item));
121
122
// Real-time progress updates
123
let progressInterval;
124
125
const { results } = await PromisePool
126
.for(items)
127
.onTaskStarted((item, pool) => {
128
// Start progress monitoring on first task
129
if (!progressInterval) {
130
progressInterval = setInterval(() => {
131
const progress = pool.processedPercentage();
132
const active = pool.activeTasksCount();
133
const processed = pool.processedCount();
134
135
console.log(`Progress: ${progress.toFixed(1)}% (${processed} completed, ${active} active)`);
136
}, 1000);
137
}
138
})
139
.onTaskFinished((item, pool) => {
140
// Clear progress monitoring when done
141
if (pool.processedPercentage() === 100) {
142
clearInterval(progressInterval);
143
console.log("Processing complete!");
144
}
145
})
146
.process(async (item) => processItem(item));
147
```
148
149
## Progress Tracking Patterns
150
151
### Pattern 1: Simple Progress Bar
152
153
Basic progress indication with percentage completion.
154
155
```typescript
156
function createProgressBar(total: number) {
157
let current = 0;
158
159
return {
160
update: (processed: number) => {
161
current = processed;
162
const percentage = (current / total * 100).toFixed(1);
163
const filled = Math.floor(current / total * 50);
164
const empty = 50 - filled;
165
166
const bar = 'β'.repeat(filled) + 'β'.repeat(empty);
167
process.stdout.write(`\r[${bar}] ${percentage}% (${current}/${total})`);
168
},
169
complete: () => {
170
process.stdout.write('\nβ Complete!\n');
171
}
172
};
173
}
174
175
const progressBar = createProgressBar(items.length);
176
177
await PromisePool
178
.for(items)
179
.onTaskFinished((item, pool) => {
180
progressBar.update(pool.processedCount());
181
182
if (pool.processedPercentage() === 100) {
183
progressBar.complete();
184
}
185
})
186
.process(async (item) => processItem(item));
187
```
188
189
### Pattern 2: Detailed Progress Dashboard
190
191
Comprehensive monitoring with multiple metrics.
192
193
```typescript
194
class ProgressDashboard {
195
private startTime = Date.now();
196
private lastUpdate = Date.now();
197
198
update(item: any, pool: Statistics<any> & UsesConcurrency) {
199
const now = Date.now();
200
const elapsed = now - this.startTime;
201
const processed = pool.processedCount();
202
const percentage = pool.processedPercentage();
203
const rate = processed / (elapsed / 1000); // items per second
204
205
console.clear();
206
console.log('π Promise Pool Progress Dashboard');
207
console.log('β'.repeat(40));
208
console.log(`Progress: ${percentage.toFixed(1)}%`);
209
console.log(`Processed: ${processed} items`);
210
console.log(`Active: ${pool.activeTasksCount()}/${pool.concurrency()}`);
211
console.log(`Rate: ${rate.toFixed(2)} items/sec`);
212
console.log(`Elapsed: ${(elapsed / 1000).toFixed(1)}s`);
213
214
if (percentage > 0) {
215
const eta = (elapsed / percentage * (100 - percentage)) / 1000;
216
console.log(`ETA: ${eta.toFixed(1)}s`);
217
}
218
}
219
}
220
221
const dashboard = new ProgressDashboard();
222
223
await PromisePool
224
.for(items)
225
.onTaskFinished((item, pool) => {
226
dashboard.update(item, pool);
227
})
228
.process(async (item) => processItem(item));
229
```
230
231
### Pattern 3: Event-Based Progress Tracking
232
233
Emit events for external progress monitoring systems.
234
235
```typescript
236
import EventEmitter from 'events';
237
238
class PoolProgressEmitter extends EventEmitter {
239
track<T>(pool: PromisePool<T>) {
240
return pool
241
.onTaskStarted((item, pool) => {
242
this.emit('taskStarted', {
243
item,
244
activeCount: pool.activeTasksCount(),
245
processedCount: pool.processedCount(),
246
percentage: pool.processedPercentage()
247
});
248
})
249
.onTaskFinished((item, pool) => {
250
this.emit('taskFinished', {
251
item,
252
activeCount: pool.activeTasksCount(),
253
processedCount: pool.processedCount(),
254
percentage: pool.processedPercentage()
255
});
256
257
if (pool.processedPercentage() === 100) {
258
this.emit('completed', {
259
totalProcessed: pool.processedCount(),
260
processedItems: pool.processedItems()
261
});
262
}
263
});
264
}
265
}
266
267
// Usage
268
const progressEmitter = new PoolProgressEmitter();
269
270
progressEmitter.on('taskStarted', (data) => {
271
console.log(`Task started: ${data.percentage.toFixed(1)}% complete`);
272
});
273
274
progressEmitter.on('taskFinished', (data) => {
275
console.log(`Task finished: ${data.processedCount} items processed`);
276
});
277
278
progressEmitter.on('completed', (data) => {
279
console.log(`All done! Processed ${data.totalProcessed} items`);
280
});
281
282
await progressEmitter
283
.track(PromisePool.for(items))
284
.process(async (item) => processItem(item));
285
```
286
287
### Pattern 4: Progress with Error Tracking
288
289
Combine progress tracking with error monitoring.
290
291
```typescript
292
class ProgressWithErrors {
293
private errors: any[] = [];
294
private processed = 0;
295
296
trackProgress<T>(pool: PromisePool<T>) {
297
return pool
298
.onTaskFinished((item, pool) => {
299
this.processed++;
300
this.logProgress(pool);
301
})
302
.handleError((error, item, pool) => {
303
this.errors.push({ error, item });
304
console.error(`β Error processing ${item}: ${error.message}`);
305
306
// Continue processing other items
307
return;
308
});
309
}
310
311
private logProgress(pool: Statistics<any>) {
312
const percentage = pool.processedPercentage();
313
const errorRate = (this.errors.length / this.processed * 100).toFixed(1);
314
315
console.log(`β Progress: ${percentage.toFixed(1)}% (${this.errors.length} errors, ${errorRate}% error rate)`);
316
}
317
318
getSummary() {
319
return {
320
totalProcessed: this.processed,
321
totalErrors: this.errors.length,
322
errorRate: (this.errors.length / this.processed * 100).toFixed(1) + '%',
323
errors: this.errors
324
};
325
}
326
}
327
328
// Usage
329
const tracker = new ProgressWithErrors();
330
331
await tracker
332
.trackProgress(PromisePool.for(items))
333
.process(async (item) => {
334
// Some items may throw errors
335
if (Math.random() < 0.1) {
336
throw new Error(`Random error for ${item}`);
337
}
338
return processItem(item);
339
});
340
341
console.log('Final Summary:', tracker.getSummary());
342
```