To better support concurrency, add a Cache.lock primitive which would look something like
with cache.lock(prefix, url) as lock:
previous = lock.get(schema_version)
# ...
lock.save(current)
While a lock is held on a file, any other attempt at acquiring that lock should block.