| 1409 | } |
| 1410 | |
| 1411 | async fn prefetch_task( |
| 1412 | state: Arc<AppState>, |
| 1413 | mut prefetch_rx: Receiver<PrefetchReq>, |
| 1414 | mut rx: broadcast::Receiver<bool>, |
| 1415 | ) { |
| 1416 | info!(immediate = true, "Spawning prefetch task ..."); |
| 1417 | |
| 1418 | let mut req_cache = LruCache::new(NonZeroUsize::new(64).unwrap()); |
| 1419 | |
| 1420 | loop { |
| 1421 | tokio::select! { |
| 1422 | _ = rx.recv() => { break; } |
| 1423 | _ = sleep(Duration::from_secs(300)) => { |
| 1424 | // Do nothing, this is to make us loop and check the running state. |
| 1425 | debug!("prefetch loop idle"); |
| 1426 | } |
| 1427 | got = prefetch_rx.recv() => { |
| 1428 | async { |
| 1429 | match got { |
| 1430 | Some(PrefetchReq { |
| 1431 | cache_key, |
| 1432 | fetch_url, |
| 1433 | tmp_file, |
| 1434 | submit_tx, |
| 1435 | cls |
| 1436 | }) => { |
| 1437 | trace!("received a prefetch operation"); |
| 1438 | let debounce_t = req_cache.get(&cache_key) |
| 1439 | .map(|inst: &Instant| inst.elapsed().as_secs()) |
| 1440 | .unwrap_or(DEBOUNCE + 1); |
| 1441 | let debounce = debounce_t < DEBOUNCE; |
| 1442 | |
| 1443 | if debounce { |
| 1444 | debug!(immediate = true, "Skipping debounce item {}", cache_key.display()); |
| 1445 | } else { |
| 1446 | // Sometimes if the dl is large, we can accidentally trigger a second dl because the cache |
| 1447 | // hasn't finished crc32c yet. So we need a tiny cache to debounce repeat dl's. |
| 1448 | req_cache.put(cache_key.clone(), Instant::now()); |
| 1449 | prefetch_dl_task(state.client.clone(), fetch_url, submit_tx, cache_key, tmp_file, cls).await; |
| 1450 | } |
| 1451 | } |
| 1452 | None => { |
| 1453 | // channels dead. |
| 1454 | warn!("prefetch channel has died"); |
| 1455 | // return; |
| 1456 | } |
| 1457 | } |
| 1458 | } |
| 1459 | .instrument(tracing::info_span!("prefetch_task")) |
| 1460 | .await; |
| 1461 | } |
| 1462 | } |
| 1463 | } |
| 1464 | |
| 1465 | warn!(immediate = true, "Stopping prefetch task."); |
| 1466 | } |
| 1467 | |
| 1468 | async fn ipxe_static(extract::Path(fname): extract::Path<PathBuf>) -> Response { |