The decorator stack¶
Each phase is built by stacking three decorators over a function that processes
a single row. concurrent turns that single-row function into a list
function:
@concurrent(workers) # fan out over a list of rows
@retry(3) # retry each row with exponential backoff
@row_cache(cache_dir) # skip rows already on disk
def step(row):
...
return result
The decorators compose bottom-up:
row_cache— innermost. Checks whether a cache file exists for this row; if so, returns the cached result without calling the function. On success, writes the result to disk before returning. See Caching & resume for cache locations and key logic.retry— wrapsrow_cache. If the inner call raises, retries up to 3 times with exponential backoff. Transient LLM API errors are recovered here.concurrent— outermost. Accepts a list of rows and fans them out across a thread pool, collecting results in the original order.
workers=1 disables threading and runs synchronously, used in tests for deterministic behavior.