~/problems / Pools & pipelines / Thread pool / concurrent crawler

Fastest weather station wins

easy ~15 min

A sailing app needs the current wind speed. Several weather stations report it, but they are flaky: some answer quickly, some slowly, some fail with an exception. Any one good answer is enough.

Implement first_reading(stations, read, max_workers) -> tuple:

  • Call read(station) for the stations using a thread pool of at most max_workers threads.
  • Return (station, value) for the first call to finish successfully, measured by clock time, not by position in the list.
  • Calls that raise are ignored. If every call raises, raise LookupError.
  • Return as soon as you have an answer. Don't wait for the slow stations still running, and don't start stations that haven't started yet.
# read("north") takes 0.5s -> 12;  read("pier") takes 0.05s -> 9;  read("hill") raises at once
first_reading(["north", "pier", "hill"], read, 3)   # ("pier", 9) after ~0.05s
first_reading(["hill"], read, 1)                    # LookupError
first_reading([], read, 2)                          # LookupError

Constraints: max_workers >= 1, 0 <= len(stations) <= 100.

Show hint

Submit every station, then loop over concurrent.futures.as_completed(futures) and return the first one whose future.exception() is None. The catch: leaving a with ThreadPoolExecutor(...) block waits for every running call. Create the pool yourself and, before returning, call pool.shutdown(wait=False, cancel_futures=True).

Topic: Thread pool / concurrent crawler. ThreadPoolExecutor, asyncio, thread-safe visited set.

0:00
Ctrl ' run · Ctrl ↵ submit
esc