Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Keep track of last access time for local media #2783

Merged
merged 3 commits into from
Jan 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions synapse/rest/media/v1/media_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
logger = logging.getLogger(__name__)


UPDATE_RECENTLY_ACCESSED_REMOTES_TS = 60 * 1000
UPDATE_RECENTLY_ACCESSED_TS = 60 * 1000


class MediaRepository(object):
Expand All @@ -75,6 +75,7 @@ def __init__(self, hs):
self.remote_media_linearizer = Linearizer(name="media_remote")

self.recently_accessed_remotes = set()
self.recently_accessed_locals = set()

# List of StorageProviders where we should search for media and
# potentially upload to.
Expand All @@ -99,19 +100,34 @@ def __init__(self, hs):
)

self.clock.looping_call(
self._update_recently_accessed_remotes,
UPDATE_RECENTLY_ACCESSED_REMOTES_TS
self._update_recently_accessed,
UPDATE_RECENTLY_ACCESSED_TS,
)

@defer.inlineCallbacks
def _update_recently_accessed_remotes(self):
media = self.recently_accessed_remotes
def _update_recently_accessed(self):
remote_media = self.recently_accessed_remotes
self.recently_accessed_remotes = set()

local_media = self.recently_accessed_locals
self.recently_accessed_locals = set()

yield self.store.update_cached_last_access_time(
media, self.clock.time_msec()
local_media, remote_media, self.clock.time_msec()
)

def mark_recently_accessed(self, server_name, media_id):
"""Mark the given media as recently accessed.

Args:
server_name (str|None): Origin server of media, or None if local
media_id (str): The media ID of the content
"""
if server_name:
self.recently_accessed_remotes.add((server_name, media_id))
else:
self.recently_accessed_locals.add(media_id)

@defer.inlineCallbacks
def create_content(self, media_type, upload_name, content, content_length,
auth_user):
Expand Down Expand Up @@ -173,6 +189,8 @@ def get_local_media(self, request, media_id, name):
respond_404(request)
return

self.mark_recently_accessed(None, media_id)

media_type = media_info["media_type"]
media_length = media_info["media_length"]
upload_name = name if name else media_info["upload_name"]
Expand Down Expand Up @@ -204,7 +222,7 @@ def get_remote_media(self, request, server_name, media_id, name):
Deferred: Resolves once a response has successfully been written
to request
"""
self.recently_accessed_remotes.add((server_name, media_id))
self.mark_recently_accessed(server_name, media_id)

# We linearize here to ensure that we don't try and download remote
# media multiple times concurrently
Expand Down
2 changes: 2 additions & 0 deletions synapse/rest/media/v1/thumbnail_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def _async_render_GET(self, request):
yield self._respond_local_thumbnail(
request, media_id, width, height, method, m_type
)
self.media_repo.mark_recently_accessed(server_name, media_id)
else:
if self.dynamic_thumbnails:
yield self._select_or_generate_remote_thumbnail(
Expand All @@ -78,6 +79,7 @@ def _async_render_GET(self, request):
request, server_name, media_id,
width, height, method, m_type
)
self.media_repo.mark_recently_accessed(None, media_id)

@defer.inlineCallbacks
def _respond_local_thumbnail(self, request, media_id, width, height,
Expand Down
23 changes: 20 additions & 3 deletions synapse/storage/media_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,33 @@ def store_cached_remote_media(self, origin, media_id, media_type,
desc="store_cached_remote_media",
)

def update_cached_last_access_time(self, origin_id_tuples, time_ts):
def update_cached_last_access_time(self, local_media, remote_media, time_ms):
"""Updates the last access time of the given media

Args:
local_media (iterable[str]): Set of media_ids
remote_media (iterable[(str, str)]): Set of (server_name, media_id)
time_ms: Current time in milliseconds
"""
def update_cache_txn(txn):
sql = (
"UPDATE remote_media_cache SET last_access_ts = ?"
" WHERE media_origin = ? AND media_id = ?"
)

txn.executemany(sql, (
(time_ts, media_origin, media_id)
for media_origin, media_id in origin_id_tuples
(time_ms, media_origin, media_id)
for media_origin, media_id in remote_media
))

sql = (
"UPDATE local_media_repository SET last_access_ts = ?"
" WHERE media_id = ?"
)

txn.executemany(sql, (
(time_ms, media_id)
for media_id in local_media
))

return self.runInteraction("update_cached_last_access_time", update_cache_txn)
Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/prepare_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# Remember to update this number every time a change is made to database
# schema files, so the users will be informed on server restarts.
SCHEMA_VERSION = 46
SCHEMA_VERSION = 47

dir_path = os.path.abspath(os.path.dirname(__file__))

Expand Down
16 changes: 16 additions & 0 deletions synapse/storage/schema/delta/47/last_access_media.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* Copyright 2018 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

ALTER TABLE local_media_repository ADD COLUMN last_access_ts BIGINT;