From 9accd63a387013081ef0035b919bd2c32910c752 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 30 Nov 2018 12:04:38 +0000 Subject: [PATCH 1/2] Initial patch from Erik --- synapse/rest/client/v1/room.py | 25 ++++++++++++++++++++ synapse/storage/events_worker.py | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py index fcfe7857f6..218dbb93ff 100644 --- a/synapse/rest/client/v1/room.py +++ b/synapse/rest/client/v1/room.py @@ -825,6 +825,30 @@ class JoinedRoomsRestServlet(ClientV1RestServlet): defer.returnValue((200, {"joined_rooms": list(room_ids)})) +class TimestampLookupRestServlet(ClientV1RestServlet): + PATTERNS = client_path_patterns("/rooms/(?P[^/]*)/timestamp_to_event$") + + def __init__(self, hs): + super(TimestampLookupRestServlet, self).__init__(hs) + self.store = hs.get_datastore() + + @defer.inlineCallbacks + def on_GET(self, request, room_id): + requester = yield self.auth.get_user_by_req(request) + yield self.auth.check_joined_room(room_id, requester.user.to_string()) + + timestamp = parse_integer(request, "ts") + thread_id = parse_integer(request, "thread_id", 0) + + event_id = yield self.store.get_event_for_timestamp( + room_id, thread_id, timestamp, + ) + + defer.returnValue((200, { + "event_id": event_id, + })) + + def register_txn_path(servlet, regex_string, http_server, with_get=False): """Registers a transaction-based path. @@ -874,6 +898,7 @@ def register_servlets(hs, http_server): JoinedRoomsRestServlet(hs).register(http_server) RoomEventServlet(hs).register(http_server) RoomEventContextServlet(hs).register(http_server) + TimestampLookupRestServlet(hs).register(http_server) def register_deprecated_servlets(hs, http_server): diff --git a/synapse/storage/events_worker.py b/synapse/storage/events_worker.py index a8326f5296..e4d8562396 100644 --- a/synapse/storage/events_worker.py +++ b/synapse/storage/events_worker.py @@ -526,3 +526,43 @@ class EventsWorkerStore(SQLBaseStore): return res return self.runInteraction("get_rejection_reasons", f) + + def get_event_for_timestamp(self, room_id, thread_id, timestamp): + sql_template = """ + SELECT event_id, origin_server_ts FROM events + WHERE + origin_server_ts %s ? + AND room_id = ? + AND thread_id = ? + ORDER BY origin_server_ts + LIMIT 1; + """ + + def f(txn): + txn.execute(sql_template % ("<=",), (timestamp, room_id, thread_id)) + row = txn.fetchone() + if row: + event_id_before, ts_before = row + else: + event_id_before, ts_before = None, None + + txn.execute(sql_template % (">=",), (timestamp, room_id, thread_id)) + row = txn.fetchone() + if row: + event_id_after, ts_after = row + else: + event_id_after, ts_after = None, None + + if event_id_before and event_id_before: + # Return the closest one + if (timestamp - ts_before) < (ts_after - timestamp): + return event_id_before + else: + return event_id_after + + if event_id_before: + return event_id_before + + return event_id_after + + return self.runInteraction("get_event_for_timestamp", f) From 080025e5331d4d51943590800adb9c6c5257a047 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 30 Nov 2018 12:09:33 +0000 Subject: [PATCH 2/2] Fix buglet and remove thread_id stuff --- synapse/rest/client/v1/room.py | 3 +-- synapse/storage/events_worker.py | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py index 218dbb93ff..f296257b11 100644 --- a/synapse/rest/client/v1/room.py +++ b/synapse/rest/client/v1/room.py @@ -838,10 +838,9 @@ class TimestampLookupRestServlet(ClientV1RestServlet): yield self.auth.check_joined_room(room_id, requester.user.to_string()) timestamp = parse_integer(request, "ts") - thread_id = parse_integer(request, "thread_id", 0) event_id = yield self.store.get_event_for_timestamp( - room_id, thread_id, timestamp, + room_id, timestamp, ) defer.returnValue((200, { diff --git a/synapse/storage/events_worker.py b/synapse/storage/events_worker.py index e4d8562396..c5fee97ac9 100644 --- a/synapse/storage/events_worker.py +++ b/synapse/storage/events_worker.py @@ -527,33 +527,32 @@ class EventsWorkerStore(SQLBaseStore): return self.runInteraction("get_rejection_reasons", f) - def get_event_for_timestamp(self, room_id, thread_id, timestamp): + def get_event_for_timestamp(self, room_id, timestamp): sql_template = """ SELECT event_id, origin_server_ts FROM events WHERE origin_server_ts %s ? AND room_id = ? - AND thread_id = ? ORDER BY origin_server_ts LIMIT 1; """ def f(txn): - txn.execute(sql_template % ("<=",), (timestamp, room_id, thread_id)) + txn.execute(sql_template % ("<=",), (timestamp, room_id)) row = txn.fetchone() if row: event_id_before, ts_before = row else: event_id_before, ts_before = None, None - txn.execute(sql_template % (">=",), (timestamp, room_id, thread_id)) + txn.execute(sql_template % (">=",), (timestamp, room_id)) row = txn.fetchone() if row: event_id_after, ts_after = row else: event_id_after, ts_after = None, None - if event_id_before and event_id_before: + if event_id_before and event_id_after: # Return the closest one if (timestamp - ts_before) < (ts_after - timestamp): return event_id_before