Don't reuse source but instead copy from primary media store to backup

This commit is contained in:
Erik Johnston 2017-10-13 14:11:34 +01:00
parent b92a8e6e4a
commit 2b24416e90
2 changed files with 9 additions and 22 deletions

View File

@ -95,7 +95,7 @@ class MediaRepository(object):
os.makedirs(dirname) os.makedirs(dirname)
@staticmethod @staticmethod
def _write_file_synchronously(source, fname, close_source=False): def _write_file_synchronously(source, fname):
"""Write `source` to the path `fname` synchronously. Should be called """Write `source` to the path `fname` synchronously. Should be called
from a thread. from a thread.
@ -109,16 +109,11 @@ class MediaRepository(object):
with open(fname, "wb") as f: with open(fname, "wb") as f:
shutil.copyfileobj(source, f) shutil.copyfileobj(source, f)
if close_source:
source.close()
@defer.inlineCallbacks @defer.inlineCallbacks
def write_to_file_and_backup(self, source, path): def write_to_file_and_backup(self, source, path):
"""Write `source` to the on disk media store, and also the backup store """Write `source` to the on disk media store, and also the backup store
if configured. if configured.
Will close source once finished.
Args: Args:
source: A file like object that should be written source: A file like object that should be written
path (str): Relative path to write file to path (str): Relative path to write file to
@ -134,37 +129,31 @@ class MediaRepository(object):
)) ))
# Write to backup repository # Write to backup repository
yield self.copy_to_backup(source, path) yield self.copy_to_backup(path)
defer.returnValue(fname) defer.returnValue(fname)
@defer.inlineCallbacks @defer.inlineCallbacks
def copy_to_backup(self, source, path): def copy_to_backup(self, path):
"""Copy file like object source to the backup media store, if configured. """Copy a file from the primary to backup media store, if configured.
Will close source after its done.
Args: Args:
source: A file like object that should be written
path(str): Relative path to write file to path(str): Relative path to write file to
""" """
if self.backup_base_path: if self.backup_base_path:
primary_fname = os.path.join(self.primary_base_path, path)
backup_fname = os.path.join(self.backup_base_path, path) backup_fname = os.path.join(self.backup_base_path, path)
# We can either wait for successful writing to the backup repository # We can either wait for successful writing to the backup repository
# or write in the background and immediately return # or write in the background and immediately return
if self.synchronous_backup_media_store: if self.synchronous_backup_media_store:
yield make_deferred_yieldable(threads.deferToThread( yield make_deferred_yieldable(threads.deferToThread(
self._write_file_synchronously, source, backup_fname, shutil.copyfile, primary_fname, backup_fname,
close_source=True,
)) ))
else: else:
preserve_fn(threads.deferToThread)( preserve_fn(threads.deferToThread)(
self._write_file_synchronously, source, backup_fname, shutil.copyfile, primary_fname, backup_fname,
close_source=True,
) )
else:
source.close()
@defer.inlineCallbacks @defer.inlineCallbacks
def create_content(self, media_type, upload_name, content, content_length, def create_content(self, media_type, upload_name, content, content_length,
@ -280,8 +269,7 @@ class MediaRepository(object):
server_name, media_id) server_name, media_id)
raise SynapseError(502, "Failed to fetch remote media") raise SynapseError(502, "Failed to fetch remote media")
# Will close the file after its done yield self.copy_to_backup(fpath)
yield self.copy_to_backup(open(fname), fpath)
media_type = headers["Content-Type"][0] media_type = headers["Content-Type"][0]
time_now_ms = self.clock.time_msec() time_now_ms = self.clock.time_msec()

View File

@ -275,8 +275,7 @@ class PreviewUrlResource(Resource):
) )
# FIXME: pass through 404s and other error messages nicely # FIXME: pass through 404s and other error messages nicely
# Will close the file after its done yield self.media_repo.copy_to_backup(fpath)
yield self.media_repo.copy_to_backup(open(fname), fpath)
media_type = headers["Content-Type"][0] media_type = headers["Content-Type"][0]
time_now_ms = self.clock.time_msec() time_now_ms = self.clock.time_msec()