miracle2k/webassets — pull request #313 by danc86 (2014-05-07 02:11:46+00:00)
Title: FilesystemCache is not safe for multiple processes

When multiple processes are sharing a filesystem cache directory, the cache files can be corrupted (contents written into the same file multiple times). A process may also see incomplete or empty cache files if it reads from cache while another process is in the middle of writing to it.

Currently the filesystem cache papers over these issues by using `safe_pickle`: it essentially pretends that a cache entry doesn't exist if the cache file was empty or corrupted.

You can see the problem in action by hacking up the source a bit:
1. Add a `print` or `warnings.warn` when a cache file cannot be unpickled
2. In the `FilesystemCache.set` method, add a call to `time.sleep` in between `open()` and `.write()`. This simulates a really slow filesystem so that you can hit the race.
3. Configure your web app to use autobuild or build assets during startup
4. Run your application in a container with multiple worker processes, such as gunicorn, or mod_wsgi with processes > 1
5. Send two HTTP requests in quick succession

```
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/222379389394b0c9e1b8bcad1503612e
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/222379389394b0c9e1b8bcad1503612e
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/ac8e8d29d045830c4bbb7f2521bb5862
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/ac8e8d29d045830c4bbb7f2521bb5862
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/f573b77d26195aaf40a7f663e8755461
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/f573b77d26195aaf40a7f663e8755461
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/9975a51d4cccc75e089f002a7fa664b5
/usr/lib/python2.6/site-packages/webassets/cache.py:185: UserWarning: Ignoring corrupted cache file assets-cache/.webassets-cache/9975a51d4cccc75e089f002a7fa664b5
warnings.warn('Ignoring corrupted cache file %s' % filename)
PRETENDING TO WRITE VERY SLOWLY TO assets-cache/.webassets-cache/9975a51d4cccc75e089f002a7fa664b5
```

The filesystem cache should use the standard write-then-rename dance to ensure that cache entries only become visible once they are fully written.