(
urls: Iterable[str],
checker: Callable[[str], Any],
workers: int,
)
| 524 | |
| 525 | |
| 526 | def check_urls_parallel( |
| 527 | urls: Iterable[str], |
| 528 | checker: Callable[[str], Any], |
| 529 | workers: int, |
| 530 | ) -> Dict[str, FeedCheckResult]: |
| 531 | url_list = sorted(set(urls)) |
| 532 | if not url_list: |
| 533 | return {} |
| 534 | max_workers = max(1, min(workers, len(url_list))) |
| 535 | results: Dict[str, FeedCheckResult] = {} |
| 536 | with ThreadPoolExecutor(max_workers=max_workers) as executor: |
| 537 | future_to_url = {executor.submit(checker, url): url for url in url_list} |
| 538 | for future in as_completed(future_to_url): |
| 539 | url = future_to_url[future] |
| 540 | try: |
| 541 | results[url] = coerce_check_result(future.result()) |
| 542 | except Exception as exc: |
| 543 | results[url] = FeedCheckResult( |
| 544 | alive=False, |
| 545 | kind="transient_fail", |
| 546 | reason=f"checker_exception:{type(exc).__name__}", |
| 547 | ) |
| 548 | return results |
| 549 | |
| 550 | |
| 551 | def run_sync( |
no test coverage detected