(fetch_days: int)
| 1203 | return [] |
| 1204 | start_day = (today - timedelta(days=max(1, int(fetch_days or 1)) - 1)).date() |
| 1205 | start_date = start_day.strftime("%Y%m%d") |
| 1206 | per_category_limit = max(1, int(math.ceil(limit_per_source / max(1, len(arxiv_categories))))) |
| 1207 | |
| 1208 | def fetch_one_category(category: str) -> List[Dict]: |
| 1209 | print(f"Fetching from arXiv {category} ({start_date} to {end_date})...") |
| 1210 | category_papers = arxiv_fetch_by_date( |
| 1211 | start_date=start_date, |
| 1212 | end_date=end_date, |
| 1213 | categories=[category], |
| 1214 | limit=per_category_limit, |
| 1215 | ) or [] |
| 1216 | category_papers = [ |
| 1217 | paper for paper in category_papers |
| 1218 | if _paper_date_in_window(paper, start_day, end_day) |
| 1219 | ] |
| 1220 | if not category_papers and callable(arxiv_fetch_recent_list_page): |
| 1221 | print(f" arXiv API returned 0 papers for {category}; fetching recent list page...") |
| 1222 | category_papers = arxiv_fetch_recent_list_page( |
| 1223 | category=category, |
| 1224 | limit=per_category_limit, |
| 1225 | ) or [] |
| 1226 | category_papers = [ |
| 1227 | paper for paper in category_papers |
| 1228 | if _paper_date_in_window(paper, start_day, end_day) |
| 1229 | ] |
| 1230 | return category_papers |
| 1231 | |
| 1232 | papers: List[Dict] = [] |
| 1233 | # One independent API call per category; the serial loop this replaces |
| 1234 | # measured 13.1s for 4 categories against ~1.1s for one. executor.map |
| 1235 | # preserves category order so downstream dedup stays deterministic. |
| 1236 | max_workers = min(_env_positive_int("PAPERFLOW_MAX_CONCURRENCY", default=5), len(arxiv_categories)) |
| 1237 | if len(arxiv_categories) > 1 and max_workers > 1: |
| 1238 | with ThreadPoolExecutor(max_workers=max_workers) as executor: |
| 1239 | results = list(executor.map(fetch_one_category, arxiv_categories)) |
| 1240 | else: |
| 1241 | results = [fetch_one_category(category) for category in arxiv_categories] |
| 1242 | |
| 1243 | for category_papers in results: |
| 1244 | papers.extend(category_papers) |
| 1245 | if category_papers: |
no test coverage detected