UNPKG

dnsweeper

Version:

Advanced CLI tool for DNS record risk analysis and cleanup. Features CSV import for Cloudflare/Route53, automated risk assessment, and parallel DNS validation.

122 lines 3.76 kB
/** * 並列実行制御ユーティリティ */ /** * 複数のPromiseを並列実行数を制限して実行 */ export async function runConcurrent(tasks, options = {}) { const { concurrency = 10, onProgress } = options; if (tasks.length === 0) { return []; } const results = new Array(tasks.length); const errors = []; let completed = 0; let index = 0; // ワーカー関数 async function worker() { while (index < tasks.length) { const currentIndex = index++; const task = tasks[currentIndex]; try { if (task) { results[currentIndex] = await task(); } } catch (error) { errors.push({ index: currentIndex, error }); } completed++; if (onProgress) { onProgress(completed, tasks.length); } } } // 指定された並列数でワーカーを起動 const workers = Array(Math.min(concurrency, tasks.length)) .fill(null) .map(() => worker()); await Promise.all(workers); // エラーがある場合は集約エラーをスロー if (errors.length > 0) { throw new AggregateError(errors.map((e) => e.error), `${errors.length} out of ${tasks.length} tasks failed`); } return results; } /** * 配列の要素に対して並列処理を実行 */ export async function mapConcurrent(items, mapper, options = {}) { const tasks = items.map((item, index) => () => mapper(item, index)); return runConcurrent(tasks, options); } /** * 並列処理の進捗を追跡するクラス */ export class ProgressTracker { total; onUpdate; completed = 0; startTime; constructor(total, onUpdate) { this.total = total; this.onUpdate = onUpdate; this.startTime = Date.now(); } increment() { this.completed++; if (this.onUpdate) { this.onUpdate(this.getProgress()); } } getProgress() { const elapsed = Date.now() - this.startTime; const rate = this.completed / (elapsed / 1000); // items per second const remaining = this.total - this.completed; const eta = (remaining / rate) * 1000; // milliseconds return { completed: this.completed, total: this.total, percentage: Math.round((this.completed / this.total) * 100), elapsed, rate, eta: Math.round(eta), remaining, }; } } /** * バッチ処理ユーティリティ */ export async function processBatch(items, batchSize, processor) { const results = []; for (let i = 0; i < items.length; i += batchSize) { const batch = items.slice(i, i + batchSize); const batchResults = await processor(batch); results.push(...batchResults); } return results; } /** * リトライ付き並列実行 */ export async function runConcurrentWithRetry(tasks, options = {}) { const { maxRetries = 3, retryDelay = 1000, ...concurrentOptions } = options; const tasksWithRetry = tasks.map((task) => async () => { let lastError; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await task(); } catch (error) { lastError = error; if (attempt < maxRetries) { await new Promise((resolve) => setTimeout(resolve, retryDelay * (attempt + 1))); } } } throw lastError; }); return runConcurrent(tasksWithRetry, concurrentOptions); } //# sourceMappingURL=concurrent.js.map