or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-pool-management.mderror-handling.mdindex.mdpool-control.mdprogress-tracking.md

progress-tracking.mddocs/

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

```