mirror of
https://mau.dev/maunium/synapse.git
synced 2024-10-01 01:36:05 -04:00
Convert some of the media REST code to async/await (#7110)
This commit is contained in:
parent
c2db6599c8
commit
caec7d4fa0
1
changelog.d/7110.misc
Normal file
1
changelog.d/7110.misc
Normal file
@ -0,0 +1 @@
|
|||||||
|
Convert some of synapse.rest.media to async/await.
|
@ -24,7 +24,6 @@ from six import iteritems
|
|||||||
|
|
||||||
import twisted.internet.error
|
import twisted.internet.error
|
||||||
import twisted.web.http
|
import twisted.web.http
|
||||||
from twisted.internet import defer
|
|
||||||
from twisted.web.resource import Resource
|
from twisted.web.resource import Resource
|
||||||
|
|
||||||
from synapse.api.errors import (
|
from synapse.api.errors import (
|
||||||
@ -114,15 +113,14 @@ class MediaRepository(object):
|
|||||||
"update_recently_accessed_media", self._update_recently_accessed
|
"update_recently_accessed_media", self._update_recently_accessed
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _update_recently_accessed(self):
|
||||||
def _update_recently_accessed(self):
|
|
||||||
remote_media = self.recently_accessed_remotes
|
remote_media = self.recently_accessed_remotes
|
||||||
self.recently_accessed_remotes = set()
|
self.recently_accessed_remotes = set()
|
||||||
|
|
||||||
local_media = self.recently_accessed_locals
|
local_media = self.recently_accessed_locals
|
||||||
self.recently_accessed_locals = set()
|
self.recently_accessed_locals = set()
|
||||||
|
|
||||||
yield self.store.update_cached_last_access_time(
|
await self.store.update_cached_last_access_time(
|
||||||
local_media, remote_media, self.clock.time_msec()
|
local_media, remote_media, self.clock.time_msec()
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -138,8 +136,7 @@ class MediaRepository(object):
|
|||||||
else:
|
else:
|
||||||
self.recently_accessed_locals.add(media_id)
|
self.recently_accessed_locals.add(media_id)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def create_content(
|
||||||
def create_content(
|
|
||||||
self, media_type, upload_name, content, content_length, auth_user
|
self, media_type, upload_name, content, content_length, auth_user
|
||||||
):
|
):
|
||||||
"""Store uploaded content for a local user and return the mxc URL
|
"""Store uploaded content for a local user and return the mxc URL
|
||||||
@ -158,11 +155,11 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
file_info = FileInfo(server_name=None, file_id=media_id)
|
file_info = FileInfo(server_name=None, file_id=media_id)
|
||||||
|
|
||||||
fname = yield self.media_storage.store_file(content, file_info)
|
fname = await self.media_storage.store_file(content, file_info)
|
||||||
|
|
||||||
logger.info("Stored local media in file %r", fname)
|
logger.info("Stored local media in file %r", fname)
|
||||||
|
|
||||||
yield self.store.store_local_media(
|
await self.store.store_local_media(
|
||||||
media_id=media_id,
|
media_id=media_id,
|
||||||
media_type=media_type,
|
media_type=media_type,
|
||||||
time_now_ms=self.clock.time_msec(),
|
time_now_ms=self.clock.time_msec(),
|
||||||
@ -171,12 +168,11 @@ class MediaRepository(object):
|
|||||||
user_id=auth_user,
|
user_id=auth_user,
|
||||||
)
|
)
|
||||||
|
|
||||||
yield self._generate_thumbnails(None, media_id, media_id, media_type)
|
await self._generate_thumbnails(None, media_id, media_id, media_type)
|
||||||
|
|
||||||
return "mxc://%s/%s" % (self.server_name, media_id)
|
return "mxc://%s/%s" % (self.server_name, media_id)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def get_local_media(self, request, media_id, name):
|
||||||
def get_local_media(self, request, media_id, name):
|
|
||||||
"""Responds to reqests for local media, if exists, or returns 404.
|
"""Responds to reqests for local media, if exists, or returns 404.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -190,7 +186,7 @@ class MediaRepository(object):
|
|||||||
Deferred: Resolves once a response has successfully been written
|
Deferred: Resolves once a response has successfully been written
|
||||||
to request
|
to request
|
||||||
"""
|
"""
|
||||||
media_info = yield self.store.get_local_media(media_id)
|
media_info = await self.store.get_local_media(media_id)
|
||||||
if not media_info or media_info["quarantined_by"]:
|
if not media_info or media_info["quarantined_by"]:
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
return
|
return
|
||||||
@ -204,13 +200,12 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
file_info = FileInfo(None, media_id, url_cache=url_cache)
|
file_info = FileInfo(None, media_id, url_cache=url_cache)
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
yield respond_with_responder(
|
await respond_with_responder(
|
||||||
request, responder, media_type, media_length, upload_name
|
request, responder, media_type, media_length, upload_name
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def get_remote_media(self, request, server_name, media_id, name):
|
||||||
def get_remote_media(self, request, server_name, media_id, name):
|
|
||||||
"""Respond to requests for remote media.
|
"""Respond to requests for remote media.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -236,8 +231,8 @@ class MediaRepository(object):
|
|||||||
# We linearize here to ensure that we don't try and download remote
|
# We linearize here to ensure that we don't try and download remote
|
||||||
# media multiple times concurrently
|
# media multiple times concurrently
|
||||||
key = (server_name, media_id)
|
key = (server_name, media_id)
|
||||||
with (yield self.remote_media_linearizer.queue(key)):
|
with (await self.remote_media_linearizer.queue(key)):
|
||||||
responder, media_info = yield self._get_remote_media_impl(
|
responder, media_info = await self._get_remote_media_impl(
|
||||||
server_name, media_id
|
server_name, media_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -246,14 +241,13 @@ class MediaRepository(object):
|
|||||||
media_type = media_info["media_type"]
|
media_type = media_info["media_type"]
|
||||||
media_length = media_info["media_length"]
|
media_length = media_info["media_length"]
|
||||||
upload_name = name if name else media_info["upload_name"]
|
upload_name = name if name else media_info["upload_name"]
|
||||||
yield respond_with_responder(
|
await respond_with_responder(
|
||||||
request, responder, media_type, media_length, upload_name
|
request, responder, media_type, media_length, upload_name
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def get_remote_media_info(self, server_name, media_id):
|
||||||
def get_remote_media_info(self, server_name, media_id):
|
|
||||||
"""Gets the media info associated with the remote file, downloading
|
"""Gets the media info associated with the remote file, downloading
|
||||||
if necessary.
|
if necessary.
|
||||||
|
|
||||||
@ -274,8 +268,8 @@ class MediaRepository(object):
|
|||||||
# We linearize here to ensure that we don't try and download remote
|
# We linearize here to ensure that we don't try and download remote
|
||||||
# media multiple times concurrently
|
# media multiple times concurrently
|
||||||
key = (server_name, media_id)
|
key = (server_name, media_id)
|
||||||
with (yield self.remote_media_linearizer.queue(key)):
|
with (await self.remote_media_linearizer.queue(key)):
|
||||||
responder, media_info = yield self._get_remote_media_impl(
|
responder, media_info = await self._get_remote_media_impl(
|
||||||
server_name, media_id
|
server_name, media_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -286,8 +280,7 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
return media_info
|
return media_info
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _get_remote_media_impl(self, server_name, media_id):
|
||||||
def _get_remote_media_impl(self, server_name, media_id):
|
|
||||||
"""Looks for media in local cache, if not there then attempt to
|
"""Looks for media in local cache, if not there then attempt to
|
||||||
download from remote server.
|
download from remote server.
|
||||||
|
|
||||||
@ -299,7 +292,7 @@ class MediaRepository(object):
|
|||||||
Returns:
|
Returns:
|
||||||
Deferred[(Responder, media_info)]
|
Deferred[(Responder, media_info)]
|
||||||
"""
|
"""
|
||||||
media_info = yield self.store.get_cached_remote_media(server_name, media_id)
|
media_info = await self.store.get_cached_remote_media(server_name, media_id)
|
||||||
|
|
||||||
# file_id is the ID we use to track the file locally. If we've already
|
# file_id is the ID we use to track the file locally. If we've already
|
||||||
# seen the file then reuse the existing ID, otherwise genereate a new
|
# seen the file then reuse the existing ID, otherwise genereate a new
|
||||||
@ -317,19 +310,18 @@ class MediaRepository(object):
|
|||||||
logger.info("Media is quarantined")
|
logger.info("Media is quarantined")
|
||||||
raise NotFoundError()
|
raise NotFoundError()
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
if responder:
|
if responder:
|
||||||
return responder, media_info
|
return responder, media_info
|
||||||
|
|
||||||
# Failed to find the file anywhere, lets download it.
|
# Failed to find the file anywhere, lets download it.
|
||||||
|
|
||||||
media_info = yield self._download_remote_file(server_name, media_id, file_id)
|
media_info = await self._download_remote_file(server_name, media_id, file_id)
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
return responder, media_info
|
return responder, media_info
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _download_remote_file(self, server_name, media_id, file_id):
|
||||||
def _download_remote_file(self, server_name, media_id, file_id):
|
|
||||||
"""Attempt to download the remote file from the given server name,
|
"""Attempt to download the remote file from the given server name,
|
||||||
using the given file_id as the local id.
|
using the given file_id as the local id.
|
||||||
|
|
||||||
@ -351,7 +343,7 @@ class MediaRepository(object):
|
|||||||
("/_matrix/media/v1/download", server_name, media_id)
|
("/_matrix/media/v1/download", server_name, media_id)
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
length, headers = yield self.client.get_file(
|
length, headers = await self.client.get_file(
|
||||||
server_name,
|
server_name,
|
||||||
request_path,
|
request_path,
|
||||||
output_stream=f,
|
output_stream=f,
|
||||||
@ -397,7 +389,7 @@ class MediaRepository(object):
|
|||||||
)
|
)
|
||||||
raise SynapseError(502, "Failed to fetch remote media")
|
raise SynapseError(502, "Failed to fetch remote media")
|
||||||
|
|
||||||
yield finish()
|
await finish()
|
||||||
|
|
||||||
media_type = headers[b"Content-Type"][0].decode("ascii")
|
media_type = headers[b"Content-Type"][0].decode("ascii")
|
||||||
upload_name = get_filename_from_headers(headers)
|
upload_name = get_filename_from_headers(headers)
|
||||||
@ -405,7 +397,7 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
logger.info("Stored remote media in file %r", fname)
|
logger.info("Stored remote media in file %r", fname)
|
||||||
|
|
||||||
yield self.store.store_cached_remote_media(
|
await self.store.store_cached_remote_media(
|
||||||
origin=server_name,
|
origin=server_name,
|
||||||
media_id=media_id,
|
media_id=media_id,
|
||||||
media_type=media_type,
|
media_type=media_type,
|
||||||
@ -423,7 +415,7 @@ class MediaRepository(object):
|
|||||||
"filesystem_id": file_id,
|
"filesystem_id": file_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
yield self._generate_thumbnails(server_name, media_id, file_id, media_type)
|
await self._generate_thumbnails(server_name, media_id, file_id, media_type)
|
||||||
|
|
||||||
return media_info
|
return media_info
|
||||||
|
|
||||||
@ -458,16 +450,15 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
return t_byte_source
|
return t_byte_source
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def generate_local_exact_thumbnail(
|
||||||
def generate_local_exact_thumbnail(
|
|
||||||
self, media_id, t_width, t_height, t_method, t_type, url_cache
|
self, media_id, t_width, t_height, t_method, t_type, url_cache
|
||||||
):
|
):
|
||||||
input_path = yield self.media_storage.ensure_media_is_in_local_cache(
|
input_path = await self.media_storage.ensure_media_is_in_local_cache(
|
||||||
FileInfo(None, media_id, url_cache=url_cache)
|
FileInfo(None, media_id, url_cache=url_cache)
|
||||||
)
|
)
|
||||||
|
|
||||||
thumbnailer = Thumbnailer(input_path)
|
thumbnailer = Thumbnailer(input_path)
|
||||||
t_byte_source = yield defer_to_thread(
|
t_byte_source = await defer_to_thread(
|
||||||
self.hs.get_reactor(),
|
self.hs.get_reactor(),
|
||||||
self._generate_thumbnail,
|
self._generate_thumbnail,
|
||||||
thumbnailer,
|
thumbnailer,
|
||||||
@ -490,7 +481,7 @@ class MediaRepository(object):
|
|||||||
thumbnail_type=t_type,
|
thumbnail_type=t_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
output_path = yield self.media_storage.store_file(
|
output_path = await self.media_storage.store_file(
|
||||||
t_byte_source, file_info
|
t_byte_source, file_info
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
@ -500,22 +491,21 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
t_len = os.path.getsize(output_path)
|
t_len = os.path.getsize(output_path)
|
||||||
|
|
||||||
yield self.store.store_local_thumbnail(
|
await self.store.store_local_thumbnail(
|
||||||
media_id, t_width, t_height, t_type, t_method, t_len
|
media_id, t_width, t_height, t_type, t_method, t_len
|
||||||
)
|
)
|
||||||
|
|
||||||
return output_path
|
return output_path
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def generate_remote_exact_thumbnail(
|
||||||
def generate_remote_exact_thumbnail(
|
|
||||||
self, server_name, file_id, media_id, t_width, t_height, t_method, t_type
|
self, server_name, file_id, media_id, t_width, t_height, t_method, t_type
|
||||||
):
|
):
|
||||||
input_path = yield self.media_storage.ensure_media_is_in_local_cache(
|
input_path = await self.media_storage.ensure_media_is_in_local_cache(
|
||||||
FileInfo(server_name, file_id, url_cache=False)
|
FileInfo(server_name, file_id, url_cache=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
thumbnailer = Thumbnailer(input_path)
|
thumbnailer = Thumbnailer(input_path)
|
||||||
t_byte_source = yield defer_to_thread(
|
t_byte_source = await defer_to_thread(
|
||||||
self.hs.get_reactor(),
|
self.hs.get_reactor(),
|
||||||
self._generate_thumbnail,
|
self._generate_thumbnail,
|
||||||
thumbnailer,
|
thumbnailer,
|
||||||
@ -537,7 +527,7 @@ class MediaRepository(object):
|
|||||||
thumbnail_type=t_type,
|
thumbnail_type=t_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
output_path = yield self.media_storage.store_file(
|
output_path = await self.media_storage.store_file(
|
||||||
t_byte_source, file_info
|
t_byte_source, file_info
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
@ -547,7 +537,7 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
t_len = os.path.getsize(output_path)
|
t_len = os.path.getsize(output_path)
|
||||||
|
|
||||||
yield self.store.store_remote_media_thumbnail(
|
await self.store.store_remote_media_thumbnail(
|
||||||
server_name,
|
server_name,
|
||||||
media_id,
|
media_id,
|
||||||
file_id,
|
file_id,
|
||||||
@ -560,8 +550,7 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
return output_path
|
return output_path
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _generate_thumbnails(
|
||||||
def _generate_thumbnails(
|
|
||||||
self, server_name, media_id, file_id, media_type, url_cache=False
|
self, server_name, media_id, file_id, media_type, url_cache=False
|
||||||
):
|
):
|
||||||
"""Generate and store thumbnails for an image.
|
"""Generate and store thumbnails for an image.
|
||||||
@ -582,7 +571,7 @@ class MediaRepository(object):
|
|||||||
if not requirements:
|
if not requirements:
|
||||||
return
|
return
|
||||||
|
|
||||||
input_path = yield self.media_storage.ensure_media_is_in_local_cache(
|
input_path = await self.media_storage.ensure_media_is_in_local_cache(
|
||||||
FileInfo(server_name, file_id, url_cache=url_cache)
|
FileInfo(server_name, file_id, url_cache=url_cache)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -600,7 +589,7 @@ class MediaRepository(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if thumbnailer.transpose_method is not None:
|
if thumbnailer.transpose_method is not None:
|
||||||
m_width, m_height = yield defer_to_thread(
|
m_width, m_height = await defer_to_thread(
|
||||||
self.hs.get_reactor(), thumbnailer.transpose
|
self.hs.get_reactor(), thumbnailer.transpose
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -620,11 +609,11 @@ class MediaRepository(object):
|
|||||||
for (t_width, t_height, t_type), t_method in iteritems(thumbnails):
|
for (t_width, t_height, t_type), t_method in iteritems(thumbnails):
|
||||||
# Generate the thumbnail
|
# Generate the thumbnail
|
||||||
if t_method == "crop":
|
if t_method == "crop":
|
||||||
t_byte_source = yield defer_to_thread(
|
t_byte_source = await defer_to_thread(
|
||||||
self.hs.get_reactor(), thumbnailer.crop, t_width, t_height, t_type
|
self.hs.get_reactor(), thumbnailer.crop, t_width, t_height, t_type
|
||||||
)
|
)
|
||||||
elif t_method == "scale":
|
elif t_method == "scale":
|
||||||
t_byte_source = yield defer_to_thread(
|
t_byte_source = await defer_to_thread(
|
||||||
self.hs.get_reactor(), thumbnailer.scale, t_width, t_height, t_type
|
self.hs.get_reactor(), thumbnailer.scale, t_width, t_height, t_type
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -646,7 +635,7 @@ class MediaRepository(object):
|
|||||||
url_cache=url_cache,
|
url_cache=url_cache,
|
||||||
)
|
)
|
||||||
|
|
||||||
output_path = yield self.media_storage.store_file(
|
output_path = await self.media_storage.store_file(
|
||||||
t_byte_source, file_info
|
t_byte_source, file_info
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
@ -656,7 +645,7 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
# Write to database
|
# Write to database
|
||||||
if server_name:
|
if server_name:
|
||||||
yield self.store.store_remote_media_thumbnail(
|
await self.store.store_remote_media_thumbnail(
|
||||||
server_name,
|
server_name,
|
||||||
media_id,
|
media_id,
|
||||||
file_id,
|
file_id,
|
||||||
@ -667,15 +656,14 @@ class MediaRepository(object):
|
|||||||
t_len,
|
t_len,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield self.store.store_local_thumbnail(
|
await self.store.store_local_thumbnail(
|
||||||
media_id, t_width, t_height, t_type, t_method, t_len
|
media_id, t_width, t_height, t_type, t_method, t_len
|
||||||
)
|
)
|
||||||
|
|
||||||
return {"width": m_width, "height": m_height}
|
return {"width": m_width, "height": m_height}
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def delete_old_remote_media(self, before_ts):
|
||||||
def delete_old_remote_media(self, before_ts):
|
old_media = await self.store.get_remote_media_before(before_ts)
|
||||||
old_media = yield self.store.get_remote_media_before(before_ts)
|
|
||||||
|
|
||||||
deleted = 0
|
deleted = 0
|
||||||
|
|
||||||
@ -689,7 +677,7 @@ class MediaRepository(object):
|
|||||||
|
|
||||||
# TODO: Should we delete from the backup store
|
# TODO: Should we delete from the backup store
|
||||||
|
|
||||||
with (yield self.remote_media_linearizer.queue(key)):
|
with (await self.remote_media_linearizer.queue(key)):
|
||||||
full_path = self.filepaths.remote_media_filepath(origin, file_id)
|
full_path = self.filepaths.remote_media_filepath(origin, file_id)
|
||||||
try:
|
try:
|
||||||
os.remove(full_path)
|
os.remove(full_path)
|
||||||
@ -705,7 +693,7 @@ class MediaRepository(object):
|
|||||||
)
|
)
|
||||||
shutil.rmtree(thumbnail_dir, ignore_errors=True)
|
shutil.rmtree(thumbnail_dir, ignore_errors=True)
|
||||||
|
|
||||||
yield self.store.delete_remote_media(origin, media_id)
|
await self.store.delete_remote_media(origin, media_id)
|
||||||
deleted += 1
|
deleted += 1
|
||||||
|
|
||||||
return {"deleted": deleted}
|
return {"deleted": deleted}
|
||||||
|
@ -165,8 +165,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
og = await make_deferred_yieldable(defer.maybeDeferred(observable.observe))
|
og = await make_deferred_yieldable(defer.maybeDeferred(observable.observe))
|
||||||
respond_with_json_bytes(request, 200, og, send_cors=True)
|
respond_with_json_bytes(request, 200, og, send_cors=True)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _do_preview(self, url, user, ts):
|
||||||
def _do_preview(self, url, user, ts):
|
|
||||||
"""Check the db, and download the URL and build a preview
|
"""Check the db, and download the URL and build a preview
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -179,7 +178,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
"""
|
"""
|
||||||
# check the URL cache in the DB (which will also provide us with
|
# check the URL cache in the DB (which will also provide us with
|
||||||
# historical previews, if we have any)
|
# historical previews, if we have any)
|
||||||
cache_result = yield self.store.get_url_cache(url, ts)
|
cache_result = await self.store.get_url_cache(url, ts)
|
||||||
if (
|
if (
|
||||||
cache_result
|
cache_result
|
||||||
and cache_result["expires_ts"] > ts
|
and cache_result["expires_ts"] > ts
|
||||||
@ -192,13 +191,13 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
og = og.encode("utf8")
|
og = og.encode("utf8")
|
||||||
return og
|
return og
|
||||||
|
|
||||||
media_info = yield self._download_url(url, user)
|
media_info = await self._download_url(url, user)
|
||||||
|
|
||||||
logger.debug("got media_info of '%s'", media_info)
|
logger.debug("got media_info of '%s'", media_info)
|
||||||
|
|
||||||
if _is_media(media_info["media_type"]):
|
if _is_media(media_info["media_type"]):
|
||||||
file_id = media_info["filesystem_id"]
|
file_id = media_info["filesystem_id"]
|
||||||
dims = yield self.media_repo._generate_thumbnails(
|
dims = await self.media_repo._generate_thumbnails(
|
||||||
None, file_id, file_id, media_info["media_type"], url_cache=True
|
None, file_id, file_id, media_info["media_type"], url_cache=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -248,14 +247,14 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
# request itself and benefit from the same caching etc. But for now we
|
# request itself and benefit from the same caching etc. But for now we
|
||||||
# just rely on the caching on the master request to speed things up.
|
# just rely on the caching on the master request to speed things up.
|
||||||
if "og:image" in og and og["og:image"]:
|
if "og:image" in og and og["og:image"]:
|
||||||
image_info = yield self._download_url(
|
image_info = await self._download_url(
|
||||||
_rebase_url(og["og:image"], media_info["uri"]), user
|
_rebase_url(og["og:image"], media_info["uri"]), user
|
||||||
)
|
)
|
||||||
|
|
||||||
if _is_media(image_info["media_type"]):
|
if _is_media(image_info["media_type"]):
|
||||||
# TODO: make sure we don't choke on white-on-transparent images
|
# TODO: make sure we don't choke on white-on-transparent images
|
||||||
file_id = image_info["filesystem_id"]
|
file_id = image_info["filesystem_id"]
|
||||||
dims = yield self.media_repo._generate_thumbnails(
|
dims = await self.media_repo._generate_thumbnails(
|
||||||
None, file_id, file_id, image_info["media_type"], url_cache=True
|
None, file_id, file_id, image_info["media_type"], url_cache=True
|
||||||
)
|
)
|
||||||
if dims:
|
if dims:
|
||||||
@ -293,7 +292,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
jsonog = json.dumps(og)
|
jsonog = json.dumps(og)
|
||||||
|
|
||||||
# store OG in history-aware DB cache
|
# store OG in history-aware DB cache
|
||||||
yield self.store.store_url_cache(
|
await self.store.store_url_cache(
|
||||||
url,
|
url,
|
||||||
media_info["response_code"],
|
media_info["response_code"],
|
||||||
media_info["etag"],
|
media_info["etag"],
|
||||||
@ -305,8 +304,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
|
|
||||||
return jsonog.encode("utf8")
|
return jsonog.encode("utf8")
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _download_url(self, url, user):
|
||||||
def _download_url(self, url, user):
|
|
||||||
# TODO: we should probably honour robots.txt... except in practice
|
# TODO: we should probably honour robots.txt... except in practice
|
||||||
# we're most likely being explicitly triggered by a human rather than a
|
# we're most likely being explicitly triggered by a human rather than a
|
||||||
# bot, so are we really a robot?
|
# bot, so are we really a robot?
|
||||||
@ -318,7 +316,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
with self.media_storage.store_into_file(file_info) as (f, fname, finish):
|
with self.media_storage.store_into_file(file_info) as (f, fname, finish):
|
||||||
try:
|
try:
|
||||||
logger.debug("Trying to get url '%s'", url)
|
logger.debug("Trying to get url '%s'", url)
|
||||||
length, headers, uri, code = yield self.client.get_file(
|
length, headers, uri, code = await self.client.get_file(
|
||||||
url, output_stream=f, max_size=self.max_spider_size
|
url, output_stream=f, max_size=self.max_spider_size
|
||||||
)
|
)
|
||||||
except SynapseError:
|
except SynapseError:
|
||||||
@ -345,7 +343,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
% (traceback.format_exception_only(sys.exc_info()[0], e),),
|
% (traceback.format_exception_only(sys.exc_info()[0], e),),
|
||||||
Codes.UNKNOWN,
|
Codes.UNKNOWN,
|
||||||
)
|
)
|
||||||
yield finish()
|
await finish()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if b"Content-Type" in headers:
|
if b"Content-Type" in headers:
|
||||||
@ -356,7 +354,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
|
|
||||||
download_name = get_filename_from_headers(headers)
|
download_name = get_filename_from_headers(headers)
|
||||||
|
|
||||||
yield self.store.store_local_media(
|
await self.store.store_local_media(
|
||||||
media_id=file_id,
|
media_id=file_id,
|
||||||
media_type=media_type,
|
media_type=media_type,
|
||||||
time_now_ms=self.clock.time_msec(),
|
time_now_ms=self.clock.time_msec(),
|
||||||
@ -393,8 +391,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
"expire_url_cache_data", self._expire_url_cache_data
|
"expire_url_cache_data", self._expire_url_cache_data
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _expire_url_cache_data(self):
|
||||||
def _expire_url_cache_data(self):
|
|
||||||
"""Clean up expired url cache content, media and thumbnails.
|
"""Clean up expired url cache content, media and thumbnails.
|
||||||
"""
|
"""
|
||||||
# TODO: Delete from backup media store
|
# TODO: Delete from backup media store
|
||||||
@ -403,12 +400,12 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
|
|
||||||
logger.info("Running url preview cache expiry")
|
logger.info("Running url preview cache expiry")
|
||||||
|
|
||||||
if not (yield self.store.db.updates.has_completed_background_updates()):
|
if not (await self.store.db.updates.has_completed_background_updates()):
|
||||||
logger.info("Still running DB updates; skipping expiry")
|
logger.info("Still running DB updates; skipping expiry")
|
||||||
return
|
return
|
||||||
|
|
||||||
# First we delete expired url cache entries
|
# First we delete expired url cache entries
|
||||||
media_ids = yield self.store.get_expired_url_cache(now)
|
media_ids = await self.store.get_expired_url_cache(now)
|
||||||
|
|
||||||
removed_media = []
|
removed_media = []
|
||||||
for media_id in media_ids:
|
for media_id in media_ids:
|
||||||
@ -430,7 +427,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
yield self.store.delete_url_cache(removed_media)
|
await self.store.delete_url_cache(removed_media)
|
||||||
|
|
||||||
if removed_media:
|
if removed_media:
|
||||||
logger.info("Deleted %d entries from url cache", len(removed_media))
|
logger.info("Deleted %d entries from url cache", len(removed_media))
|
||||||
@ -440,7 +437,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
# may have a room open with a preview url thing open).
|
# may have a room open with a preview url thing open).
|
||||||
# So we wait a couple of days before deleting, just in case.
|
# So we wait a couple of days before deleting, just in case.
|
||||||
expire_before = now - 2 * 24 * 60 * 60 * 1000
|
expire_before = now - 2 * 24 * 60 * 60 * 1000
|
||||||
media_ids = yield self.store.get_url_cache_media_before(expire_before)
|
media_ids = await self.store.get_url_cache_media_before(expire_before)
|
||||||
|
|
||||||
removed_media = []
|
removed_media = []
|
||||||
for media_id in media_ids:
|
for media_id in media_ids:
|
||||||
@ -478,7 +475,7 @@ class PreviewUrlResource(DirectServeResource):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
yield self.store.delete_url_cache_media(removed_media)
|
await self.store.delete_url_cache_media(removed_media)
|
||||||
|
|
||||||
logger.info("Deleted %d media from url cache", len(removed_media))
|
logger.info("Deleted %d media from url cache", len(removed_media))
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from twisted.internet import defer
|
|
||||||
|
|
||||||
from synapse.http.server import (
|
from synapse.http.server import (
|
||||||
DirectServeResource,
|
DirectServeResource,
|
||||||
set_cors_headers,
|
set_cors_headers,
|
||||||
@ -79,11 +77,10 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
)
|
)
|
||||||
self.media_repo.mark_recently_accessed(server_name, media_id)
|
self.media_repo.mark_recently_accessed(server_name, media_id)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _respond_local_thumbnail(
|
||||||
def _respond_local_thumbnail(
|
|
||||||
self, request, media_id, width, height, method, m_type
|
self, request, media_id, width, height, method, m_type
|
||||||
):
|
):
|
||||||
media_info = yield self.store.get_local_media(media_id)
|
media_info = await self.store.get_local_media(media_id)
|
||||||
|
|
||||||
if not media_info:
|
if not media_info:
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
@ -93,7 +90,7 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
respond_404(request)
|
respond_404(request)
|
||||||
return
|
return
|
||||||
|
|
||||||
thumbnail_infos = yield self.store.get_local_media_thumbnails(media_id)
|
thumbnail_infos = await self.store.get_local_media_thumbnails(media_id)
|
||||||
|
|
||||||
if thumbnail_infos:
|
if thumbnail_infos:
|
||||||
thumbnail_info = self._select_thumbnail(
|
thumbnail_info = self._select_thumbnail(
|
||||||
@ -114,14 +111,13 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
t_type = file_info.thumbnail_type
|
t_type = file_info.thumbnail_type
|
||||||
t_length = thumbnail_info["thumbnail_length"]
|
t_length = thumbnail_info["thumbnail_length"]
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
yield respond_with_responder(request, responder, t_type, t_length)
|
await respond_with_responder(request, responder, t_type, t_length)
|
||||||
else:
|
else:
|
||||||
logger.info("Couldn't find any generated thumbnails")
|
logger.info("Couldn't find any generated thumbnails")
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _select_or_generate_local_thumbnail(
|
||||||
def _select_or_generate_local_thumbnail(
|
|
||||||
self,
|
self,
|
||||||
request,
|
request,
|
||||||
media_id,
|
media_id,
|
||||||
@ -130,7 +126,7 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
desired_method,
|
desired_method,
|
||||||
desired_type,
|
desired_type,
|
||||||
):
|
):
|
||||||
media_info = yield self.store.get_local_media(media_id)
|
media_info = await self.store.get_local_media(media_id)
|
||||||
|
|
||||||
if not media_info:
|
if not media_info:
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
@ -140,7 +136,7 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
respond_404(request)
|
respond_404(request)
|
||||||
return
|
return
|
||||||
|
|
||||||
thumbnail_infos = yield self.store.get_local_media_thumbnails(media_id)
|
thumbnail_infos = await self.store.get_local_media_thumbnails(media_id)
|
||||||
for info in thumbnail_infos:
|
for info in thumbnail_infos:
|
||||||
t_w = info["thumbnail_width"] == desired_width
|
t_w = info["thumbnail_width"] == desired_width
|
||||||
t_h = info["thumbnail_height"] == desired_height
|
t_h = info["thumbnail_height"] == desired_height
|
||||||
@ -162,15 +158,15 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
t_type = file_info.thumbnail_type
|
t_type = file_info.thumbnail_type
|
||||||
t_length = info["thumbnail_length"]
|
t_length = info["thumbnail_length"]
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
if responder:
|
if responder:
|
||||||
yield respond_with_responder(request, responder, t_type, t_length)
|
await respond_with_responder(request, responder, t_type, t_length)
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.debug("We don't have a thumbnail of that size. Generating")
|
logger.debug("We don't have a thumbnail of that size. Generating")
|
||||||
|
|
||||||
# Okay, so we generate one.
|
# Okay, so we generate one.
|
||||||
file_path = yield self.media_repo.generate_local_exact_thumbnail(
|
file_path = await self.media_repo.generate_local_exact_thumbnail(
|
||||||
media_id,
|
media_id,
|
||||||
desired_width,
|
desired_width,
|
||||||
desired_height,
|
desired_height,
|
||||||
@ -180,13 +176,12 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if file_path:
|
if file_path:
|
||||||
yield respond_with_file(request, desired_type, file_path)
|
await respond_with_file(request, desired_type, file_path)
|
||||||
else:
|
else:
|
||||||
logger.warning("Failed to generate thumbnail")
|
logger.warning("Failed to generate thumbnail")
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _select_or_generate_remote_thumbnail(
|
||||||
def _select_or_generate_remote_thumbnail(
|
|
||||||
self,
|
self,
|
||||||
request,
|
request,
|
||||||
server_name,
|
server_name,
|
||||||
@ -196,9 +191,9 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
desired_method,
|
desired_method,
|
||||||
desired_type,
|
desired_type,
|
||||||
):
|
):
|
||||||
media_info = yield self.media_repo.get_remote_media_info(server_name, media_id)
|
media_info = await self.media_repo.get_remote_media_info(server_name, media_id)
|
||||||
|
|
||||||
thumbnail_infos = yield self.store.get_remote_media_thumbnails(
|
thumbnail_infos = await self.store.get_remote_media_thumbnails(
|
||||||
server_name, media_id
|
server_name, media_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -224,15 +219,15 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
t_type = file_info.thumbnail_type
|
t_type = file_info.thumbnail_type
|
||||||
t_length = info["thumbnail_length"]
|
t_length = info["thumbnail_length"]
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
if responder:
|
if responder:
|
||||||
yield respond_with_responder(request, responder, t_type, t_length)
|
await respond_with_responder(request, responder, t_type, t_length)
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.debug("We don't have a thumbnail of that size. Generating")
|
logger.debug("We don't have a thumbnail of that size. Generating")
|
||||||
|
|
||||||
# Okay, so we generate one.
|
# Okay, so we generate one.
|
||||||
file_path = yield self.media_repo.generate_remote_exact_thumbnail(
|
file_path = await self.media_repo.generate_remote_exact_thumbnail(
|
||||||
server_name,
|
server_name,
|
||||||
file_id,
|
file_id,
|
||||||
media_id,
|
media_id,
|
||||||
@ -243,21 +238,20 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if file_path:
|
if file_path:
|
||||||
yield respond_with_file(request, desired_type, file_path)
|
await respond_with_file(request, desired_type, file_path)
|
||||||
else:
|
else:
|
||||||
logger.warning("Failed to generate thumbnail")
|
logger.warning("Failed to generate thumbnail")
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
async def _respond_remote_thumbnail(
|
||||||
def _respond_remote_thumbnail(
|
|
||||||
self, request, server_name, media_id, width, height, method, m_type
|
self, request, server_name, media_id, width, height, method, m_type
|
||||||
):
|
):
|
||||||
# TODO: Don't download the whole remote file
|
# TODO: Don't download the whole remote file
|
||||||
# We should proxy the thumbnail from the remote server instead of
|
# We should proxy the thumbnail from the remote server instead of
|
||||||
# downloading the remote file and generating our own thumbnails.
|
# downloading the remote file and generating our own thumbnails.
|
||||||
media_info = yield self.media_repo.get_remote_media_info(server_name, media_id)
|
media_info = await self.media_repo.get_remote_media_info(server_name, media_id)
|
||||||
|
|
||||||
thumbnail_infos = yield self.store.get_remote_media_thumbnails(
|
thumbnail_infos = await self.store.get_remote_media_thumbnails(
|
||||||
server_name, media_id
|
server_name, media_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -278,8 +272,8 @@ class ThumbnailResource(DirectServeResource):
|
|||||||
t_type = file_info.thumbnail_type
|
t_type = file_info.thumbnail_type
|
||||||
t_length = thumbnail_info["thumbnail_length"]
|
t_length = thumbnail_info["thumbnail_length"]
|
||||||
|
|
||||||
responder = yield self.media_storage.fetch_media(file_info)
|
responder = await self.media_storage.fetch_media(file_info)
|
||||||
yield respond_with_responder(request, responder, t_type, t_length)
|
await respond_with_responder(request, responder, t_type, t_length)
|
||||||
else:
|
else:
|
||||||
logger.info("Failed to find any generated thumbnails")
|
logger.info("Failed to find any generated thumbnails")
|
||||||
respond_404(request)
|
respond_404(request)
|
||||||
|
Loading…
Reference in New Issue
Block a user