I've changed the Registry structure to be a chain-of-responsibility. But rather than have all Registry implementations require a 'next' registry, it is up to each implementation to say if it needs a next. So DockerRegistry is an endpoint, and if the resource isn't found there then we get back a None. The PrivateRegistry needs a next registry and, if it can't find the resource locally, will delegate to the next registry. This should make it possible to create a CacheRegistry that sits cleanly between PrivateRegistry and DockerRegistry and simply delegates off to next (i.e. DockerRegistry) when it can't find a resource, and tee the response into the cache as it streams through.
I've implemented (but not yet tested) a FileBasedCacheRegistry that delegates to another registry if it can't find the resource in the cache, and tees the resulting stream into a cache file.