LocalFileIdentifiableStore has no concurrency control across processes. Under a multi-worker WSGI deployment, two workers handling concurrent requests that modify the same object will each call commit(), write to separate temp files, and then race on os.replace(). The last writer wins silently (no exception, no conflict signal, no log entry). The earlier write is permanently lost.
CouchDB avoids this via _rev/409: the caller is forced to detect and resolve the conflict. The local file path has no equivalent mechanism.
I suggest to take an advisory lock on a stable sibling lockfile (<hash>.lock) for the duration of the write in _write_atomic(). A sibling lockfile is preferred over locking the JSON file itself because os.replace() swaps the inode, so a lock held on the old file does not carry over to the replacement.
fcntl.flock is sufficient for single-host deployments (the local file backend implies a single host by design) and is safe under uWSGI multi-worker mode. It should be wrapped in a try/finally to guarantee the lock is released even on exception or KeyboardInterrupt.
This issue has been found by @zrgt during review of #553.
LocalFileIdentifiableStorehas no concurrency control across processes. Under a multi-worker WSGI deployment, two workers handling concurrent requests that modify the same object will each callcommit(), write to separate temp files, and then race onos.replace(). The last writer wins silently (no exception, no conflict signal, no log entry). The earlier write is permanently lost.CouchDB avoids this via
_rev/409: the caller is forced to detect and resolve the conflict. The local file path has no equivalent mechanism.I suggest to take an advisory lock on a stable sibling lockfile (
<hash>.lock) for the duration of the write in_write_atomic(). A sibling lockfile is preferred over locking the JSON file itself becauseos.replace()swaps the inode, so a lock held on the old file does not carry over to the replacement.fcntl.flockis sufficient for single-host deployments (the local file backend implies a single host by design) and is safe under uWSGI multi-worker mode. It should be wrapped in atry/finallyto guarantee the lock is released even on exception orKeyboardInterrupt.This issue has been found by @zrgt during review of #553.