Skip to content

Commit 9824dd2

Browse files
committed
[FIX] Simplify BatchProcessor progress handling and logging
- Removed MultiBar dependency and replaced it with a single progress bar for improved clarity. - Updated logging to provide more concise output regarding file processing and retry attempts. - Enhanced summary output format for better readability and detail on processing results.
1 parent daf1a65 commit 9824dd2

3 files changed

Lines changed: 63 additions & 65 deletions

File tree

.yarn/install-state.gz

-1 Bytes
Binary file not shown.

packages/core/__tests__/BatchProcessor.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,6 @@ Test subtitle content
337337
expect(stats.successful).toBe(1);
338338
expect(stats.failed).toBe(0);
339339
expect(attemptCount).toBe(3); // Initial + 2 retries
340-
// Console should show retry attempts
341-
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Retrying'));
342340
});
343341

344342
it('should use custom retry delay', async () => {

packages/core/src/BatchProcessor.ts

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'fs/promises';
22
import path from 'path';
33

4-
import { SingleBar, MultiBar, Presets } from 'cli-progress';
4+
import { SingleBar, Presets } from 'cli-progress';
55
import { glob } from 'glob';
66

77
import { IBatchOptions, IBatchStats } from '@subzilla/types';
@@ -10,25 +10,14 @@ import SubtitleProcessor from './SubtitleProcessor';
1010

1111
export default class BatchProcessor {
1212
private processor: SubtitleProcessor;
13-
private multiBar: MultiBar;
14-
private mainProgressBar!: SingleBar;
15-
private directoryBars: Map<string, SingleBar>;
13+
private progressBar: SingleBar | null = null;
1614
private startTime: number = 0;
1715
private stats: IBatchStats;
1816
private shouldStop: boolean = false;
17+
private currentFile: string = '';
1918

2019
constructor() {
2120
this.processor = new SubtitleProcessor();
22-
this.multiBar = new MultiBar(
23-
{
24-
format: '{bar} {percentage}% | {value}/{total} | {title}',
25-
hideCursor: true,
26-
clearOnComplete: false,
27-
},
28-
Presets.shades_classic,
29-
);
30-
31-
this.directoryBars = new Map();
3221
this.stats = this.initializeStats();
3322
}
3423

@@ -62,7 +51,9 @@ export default class BatchProcessor {
6251
}
6352

6453
this.stats.total = files.length;
65-
console.log(`🔍 Found ${files.length} files in ${this.countDirectories(files)} directories...`);
54+
const dirCount = this.countDirectories(files);
55+
56+
console.log(`🔍 Found ${files.length} files in ${dirCount} directories\n`);
6657

6758
// Create output directory if specified
6859
if (options.common.outputDir) {
@@ -74,10 +65,19 @@ export default class BatchProcessor {
7465

7566
this.stats.directoriesProcessed = Object.keys(filesByDir).length;
7667

77-
// Initialize main progress bar
78-
this.mainProgressBar = this.multiBar.create(files.length, 0, {
79-
title: 'Total Progress',
80-
});
68+
// Initialize progress bar
69+
this.progressBar = new SingleBar(
70+
{
71+
format: ' {bar} {percentage}% | {value}/{total} files | {status}',
72+
hideCursor: true,
73+
clearOnComplete: false,
74+
barCompleteChar: '█',
75+
barIncompleteChar: '░',
76+
},
77+
Presets.shades_classic,
78+
);
79+
80+
this.progressBar.start(files.length, 0, { status: 'Starting...' });
8181

8282
// Process directories
8383
if (options.batch.parallel) {
@@ -88,17 +88,18 @@ export default class BatchProcessor {
8888

8989
// Finalize statistics
9090
this.stats.timeTaken = (Date.now() - this.startTime) / 1000;
91-
this.stats.averageTimePerFile = this.stats.timeTaken / (this.stats.successful + this.stats.failed);
91+
this.stats.averageTimePerFile = this.stats.timeTaken / (this.stats.successful + this.stats.failed) || 0;
9292

93-
// Stop progress bars
94-
this.multiBar.stop();
93+
// Stop progress bar
94+
this.progressBar.update({ status: 'Complete!' });
95+
this.progressBar.stop();
9596

9697
// Print summary
9798
this.printSummary();
9899

99100
return this.stats;
100101
} catch (error) {
101-
this.multiBar.stop();
102+
this.progressBar?.stop();
102103
throw error;
103104
}
104105
}
@@ -209,7 +210,7 @@ export default class BatchProcessor {
209210
options: IBatchOptions,
210211
): Promise<void> {
211212
const directories = Object.entries(filesByDir);
212-
const chunks = this.chunkArray(directories, options.batch.chunkSize || 3); // Use configured chunk size
213+
const chunks = this.chunkArray(directories, options.batch.chunkSize || 3);
213214

214215
for (const chunk of chunks) {
215216
if (this.shouldStop) break;
@@ -229,13 +230,6 @@ export default class BatchProcessor {
229230
private async processDirectory(dir: string, files: string[], options: IBatchOptions): Promise<void> {
230231
if (this.shouldStop) return;
231232

232-
// Create directory progress bar
233-
const dirBar = this.multiBar.create(files.length, 0, {
234-
title: `Processing ${path.basename(dir)}`,
235-
});
236-
237-
this.directoryBars.set(dir, dirBar);
238-
239233
// Create output directory structure if needed
240234
if (options.batch.preserveStructure && options.common.outputDir) {
241235
const relativePath = path.relative(process.cwd(), dir);
@@ -258,20 +252,22 @@ export default class BatchProcessor {
258252
await this.processFile(file, dir, options);
259253
}
260254
}
261-
262-
// Remove directory progress bar
263-
this.directoryBars.delete(dir);
264255
}
265256

266257
private async processFile(file: string, dir: string, options: IBatchOptions): Promise<void> {
267258
const outputPath = this.getOutputPath(file, dir, options);
268259
const dirStats = this.stats.filesByDirectory[dir];
260+
const fileName = path.basename(file);
269261

270262
dirStats.total++;
263+
this.currentFile = fileName;
264+
265+
// Update progress bar with current file
266+
this.progressBar?.update({ status: this.truncateFileName(fileName, 40) });
271267

272268
let attempts = 0;
273269
const retryCount = options.common.retryCount || 0;
274-
const maxAttempts = retryCount + 1; // Initial attempt + retry count
270+
const maxAttempts = retryCount + 1;
275271
const retryDelay = options.common.retryDelay || 1000;
276272

277273
try {
@@ -290,19 +286,17 @@ export default class BatchProcessor {
290286
dirStats.successful++;
291287
this.stats.successful++;
292288

293-
return; // Success - exit early
289+
return;
294290
} catch (error) {
295291
attempts++;
296292

297293
if (attempts < maxAttempts) {
298-
// Log retry attempt
299-
console.log(`🔄 Retrying ${file} (attempt ${attempts}/${retryCount})...`);
294+
this.progressBar?.update({ status: `Retrying ${fileName} (${attempts}/${retryCount})` });
300295
await this.delay(retryDelay);
301296

302297
continue;
303298
}
304299

305-
// All retries exhausted
306300
dirStats.failed++;
307301
this.stats.failed++;
308302
this.stats.errors.push({
@@ -317,12 +311,20 @@ export default class BatchProcessor {
317311
}
318312
}
319313
} finally {
320-
// Only increment progress bars once, after all retries are complete
321-
this.mainProgressBar.increment();
322-
this.directoryBars.get(dir)?.increment();
314+
this.progressBar?.increment();
323315
}
324316
}
325317

318+
private truncateFileName(fileName: string, maxLength: number): string {
319+
if (fileName.length <= maxLength) return fileName;
320+
321+
const ext = path.extname(fileName);
322+
const name = path.basename(fileName, ext);
323+
const availableLength = maxLength - ext.length - 3; // 3 for "..."
324+
325+
return name.substring(0, availableLength) + '...' + ext;
326+
}
327+
326328
private getOutputPath(file: string, dir: string, options: IBatchOptions): string | undefined {
327329
if (!options.common.outputDir) return undefined;
328330

@@ -362,31 +364,29 @@ export default class BatchProcessor {
362364
}
363365

364366
private printSummary(): void {
365-
console.log('\n📊 Batch Processing Summary:');
366-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━');
367-
console.log(`Total files processed: ${this.stats.total}`);
368-
console.log(`Directories processed: ${this.stats.directoriesProcessed}`);
369-
console.log(`✅ Successfully converted: ${this.stats.successful}`);
370-
console.log(`❌ Failed: ${this.stats.failed}`);
371-
console.log(`⏭️ Skipped: ${this.stats.skipped}`);
372-
console.log(`⏱️ Total time: ${this.stats.timeTaken.toFixed(2)}s`);
373-
console.log(`⚡ Average time per file: ${this.stats.averageTimePerFile.toFixed(2)}s`);
374-
375-
console.log('\n📂 Directory Statistics:');
376-
console.log('━━━━━━━━━━━━━━━━━━━━');
377-
// Object.entries(this.stats.filesByDirectory).forEach(([dir, stats]) => {
378-
// console.log(`\n${dir}:`);
379-
// console.log(` Total: ${stats.total}`);
380-
// console.log(` ✅ Success: ${stats.successful}`);
381-
// console.log(` ❌ Failed: ${stats.failed}`);
382-
// console.log(` ⏭️ Skipped: ${stats.skipped}`);
383-
// });
367+
console.log('\n');
368+
console.log('📊 Batch Processing Summary');
369+
console.log('───────────────────────────');
370+
console.log(` Total: ${this.stats.total} files in ${this.stats.directoriesProcessed} directories`);
371+
console.log(` ✓ Success: ${this.stats.successful}`);
372+
373+
if (this.stats.failed > 0) {
374+
console.log(` ✗ Failed: ${this.stats.failed}`);
375+
}
376+
377+
if (this.stats.skipped > 0) {
378+
console.log(` ⊘ Skipped: ${this.stats.skipped}`);
379+
}
380+
381+
console.log(
382+
` ⏱ Time: ${this.stats.timeTaken.toFixed(2)}s (${this.stats.averageTimePerFile.toFixed(2)}s/file)`,
383+
);
384384

385385
if (this.stats.errors.length > 0) {
386386
console.log('\n❌ Errors:');
387-
console.log('━━━━━━━━━');
387+
console.log('───────────────────────────');
388388
this.stats.errors.forEach(({ file, error }) => {
389-
console.log(`${file}: ${error}`);
389+
console.log(` ${path.basename(file)}: ${error}`);
390390
});
391391
}
392392
}

0 commit comments

Comments
 (0)