Ensure atomic writes for cache file (#78208)

* Ensure atomic writes for cache file

 helps avoid errors in highly concurrent environments
pull/78220/head
Brian Coca 2 years ago committed by GitHub
parent e10851d495
commit f6419a53f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- file backed cache plugins now handle concurrent access by making atomic updates to the files.

@ -19,9 +19,10 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import copy
import errno
import os
import tempfile
import time
import errno
from abc import abstractmethod
from collections.abc import MutableMapping
@ -156,10 +157,21 @@ class BaseFileCacheModule(BaseCacheModule):
self._cache[key] = value
cachefile = self._get_cache_file_name(key)
tmpfile_handle, tmpfile_path = tempfile.mkstemp(dir=os.path.dirname(cachefile))
try:
self._dump(value, cachefile)
except (OSError, IOError) as e:
display.warning("error in '%s' cache plugin while trying to write to %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
try:
self._dump(value, tmpfile_path)
except (OSError, IOError) as e:
display.warning("error in '%s' cache plugin while trying to write to '%s' : %s" % (self.plugin_name, tmpfile_path, to_bytes(e)))
try:
os.rename(tmpfile_path, cachefile)
except (OSError, IOError) as e:
display.warning("error in '%s' cache plugin while trying to move '%s' to '%s' : %s" % (self.plugin_name, tmpfile_path, cachefile, to_bytes(e)))
finally:
try:
os.unlink(tmpfile_path)
except OSError:
pass
def has_expired(self, key):

Loading…
Cancel
Save