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

Add endpoint to get an event at a given timestamp - MSC3030 #9445

Merged
merged 55 commits into from
Dec 2, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
91b1b36
Add endpoint to get an event at a given timestamp
erikjohnston Feb 19, 2021
8e5fa11
Update to latest REST servlet standards
MadLittleMods Jul 15, 2021
96c48ba
Merge branch 'develop' into eric/jump-to-date
MadLittleMods Jul 26, 2021
668aa4e
Remove thread_id
MadLittleMods Jul 27, 2021
5b07487
Use updated method name check_joined_room -> check_user_in_room
MadLittleMods Jul 27, 2021
f721899
Use correct requester to sender access method
MadLittleMods Jul 27, 2021
af085ab
Use up-to-date db interaction method
MadLittleMods Jul 27, 2021
065273b
Add Complement MSC feature flag
MadLittleMods Jul 28, 2021
0e0ddda
Merge branch 'develop' into eric/jump-to-date
MadLittleMods Nov 10, 2021
e321ef7
Fix query sort order so it returns the closest event before/after
MadLittleMods Nov 12, 2021
e21e4b5
Add ?dir parameter
MadLittleMods Nov 12, 2021
fa15989
Add federated /timestamp_to_event endpoint and logic to ask
MadLittleMods Nov 17, 2021
ec2695d
Determine forward extremity by edges
MadLittleMods Nov 17, 2021
22a93c3
Add experimental feature flag for MSC3030
MadLittleMods Nov 17, 2021
b311853
Document and move to unstable prefixes
MadLittleMods Nov 17, 2021
5638123
Add changelog
MadLittleMods Nov 17, 2021
612b51f
Fix lints
MadLittleMods Nov 17, 2021
654d7ae
Fix lint
MadLittleMods Nov 17, 2021
6280d36
Fix lint
MadLittleMods Nov 17, 2021
8766b0a
Filter events before handing them over federation
MadLittleMods Nov 25, 2021
86a2642
Don't spam logs for 404's
MadLittleMods Nov 25, 2021
5a2c997
Allow returning event_ids for hidden events according to history visi…
MadLittleMods Nov 25, 2021
bc3ba38
Ignore rejected events and look for gaps instead
MadLittleMods Nov 25, 2021
edac953
We only return event or raise an exception
MadLittleMods Nov 25, 2021
ab800e3
Only return ValueError from storage layer
MadLittleMods Nov 25, 2021
9800a4b
Add docstring
MadLittleMods Nov 25, 2021
8523bf3
Better description for event_next_to_gap
MadLittleMods Nov 25, 2021
f05c292
Fix lints
MadLittleMods Nov 25, 2021
984a14b
Merge branch 'develop' into eric/jump-to-date
MadLittleMods Nov 25, 2021
dae7e0a
Remove filter_events_for_server because always ok to see event_id
MadLittleMods Nov 29, 2021
87ac1ed
Rename to is_event_next_to_gap
MadLittleMods Nov 29, 2021
2a5b622
Remove extra space typo
MadLittleMods Nov 29, 2021
0610fac
Include inclusive comment on all comment docs
MadLittleMods Nov 29, 2021
183e1bf
Remove redundant continues
MadLittleMods Nov 29, 2021
5362bd3
Fix query rejections and edge cases
MadLittleMods Nov 30, 2021
76ac526
Update function name to portray what it accepts, event_id
MadLittleMods Nov 30, 2021
58d67f2
Fix backward gap detection
MadLittleMods Nov 30, 2021
63d61fc
Type the transport client for /timestamp_to_event requests
MadLittleMods Nov 30, 2021
70420e5
Optimize when we ask other federated homeservers
MadLittleMods Nov 30, 2021
a8644b9
Only return remote event when closer
MadLittleMods Nov 30, 2021
c38984c
Add origin_server_ts to client endpoint
MadLittleMods Nov 30, 2021
ed1360a
Make asserts more obvious
MadLittleMods Nov 30, 2021
13371a6
Better comments
MadLittleMods Nov 30, 2021
d137292
Also check for the event itself as a backward extremity
MadLittleMods Nov 30, 2021
662366a
Remove redundant NPE check
MadLittleMods Nov 30, 2021
dd7e689
Make more comment clear on why not and what we can use it to rely on
MadLittleMods Nov 30, 2021
e7d2120
Fix typo
MadLittleMods Nov 30, 2021
5660fde
Use federation_client and better validation
MadLittleMods Nov 30, 2021
c3c404b
Louder warnings about real problems
MadLittleMods Dec 1, 2021
1ff2db4
Optimize query to a single IN clause
MadLittleMods Dec 1, 2021
067d67a
Merge branch 'develop' into eric/jump-to-date
MadLittleMods Dec 1, 2021
5888eba
Fix lint
MadLittleMods Dec 1, 2021
68704f4
Fix mypy lints
MadLittleMods Dec 1, 2021
3ee5d0c
Use %r to protect from ascii junk
MadLittleMods Dec 2, 2021
2621e5d
Remove MSC3030 complement test flag because unknown state of tests at…
MadLittleMods Dec 2, 2021
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
2 changes: 1 addition & 1 deletion scripts-dev/complement.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ if [[ -n "$1" ]]; then
fi

# Run the tests!
go test -v -tags synapse_blacklist,msc2946,msc3083,msc2403,msc2716 -count=1 "${EXTRA_COMPLEMENT_ARGS[@]}" ./tests/...
go test -v -tags synapse_blacklist,msc2946,msc3083,msc2403,msc2716,msc3030 -count=1 "${EXTRA_COMPLEMENT_ARGS[@]}" ./tests/...
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
27 changes: 27 additions & 0 deletions synapse/rest/client/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,32 @@ def register_txn_path(
)


class TimestampLookupRestServlet(RestServlet):
PATTERNS = client_patterns("/rooms/(?P<room_id>[^/]*)/timestamp_to_event$")

def __init__(self, hs: "HomeServer"):
super().__init__()
self._auth = hs.get_auth()
self._store = hs.get_datastore()

async def on_GET(
self, request: SynapseRequest, room_id: str
) -> Tuple[int, JsonDict]:
requester = await self._auth.get_user_by_req(request)
await self._auth.check_user_in_room(room_id, requester.user.to_string())

timestamp = parse_integer(request, "ts")
direction = parse_string(request, "dir", default="f", allowed_values=["f", "b"])

event_id = await self._store.get_event_for_timestamp(
room_id, timestamp, direction
)

return 200, {
"event_id": event_id,
}
Copy link
Contributor Author

@MadLittleMods MadLittleMods Nov 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One problem I'm seeing with going with a /timestamp_to_event endpoint is that there is no way to actually paginate with /messages after getting the event_id.

We probably want to consider also returning a pagination stream token to use with the from/to on /messages

Copy link
Contributor Author

@MadLittleMods MadLittleMods Nov 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just not worry about it, we can make a separate request to get one:

https://github.com/matrix-org/complement/blob/581cb0b26e602763c4ec52e3c5f5047a2a4d95b7/tests/msc2716_test.go#L1323-L1326

// Get a pagination token for a single event
contextRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "context", someEventId}, client.WithContentType("application/json"), client.WithQueries(url.Values{
	"limit": []string{"0"},
}))



class RoomSpaceSummaryRestServlet(RestServlet):
PATTERNS = (
re.compile(
Expand Down Expand Up @@ -1239,6 +1265,7 @@ def register_servlets(
RoomAliasListServlet(hs).register(http_server)
SearchRestServlet(hs).register(http_server)
RoomCreateRestServlet(hs).register(http_server)
TimestampLookupRestServlet(hs).register(http_server)
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved

# Some servlets only get registered for the main process.
if not is_worker:
Expand Down
54 changes: 53 additions & 1 deletion synapse/storage/databases/main/events_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from twisted.internet import defer

from synapse.api.constants import EventTypes
from synapse.api.errors import NotFoundError, SynapseError
from synapse.api.errors import Codes, NotFoundError, SynapseError
from synapse.api.room_versions import (
KNOWN_ROOM_VERSIONS,
EventFormatVersions,
Expand Down Expand Up @@ -1626,3 +1626,55 @@ def _cleanup_old_transaction_ids_txn(txn):
"_cleanup_old_transaction_ids",
_cleanup_old_transaction_ids_txn,
)

async def get_event_for_timestamp(
self, room_id: str, timestamp: int, direction: str
) -> str:
sql_template = """
SELECT event_id FROM events
WHERE
origin_server_ts %s ?
AND room_id = ?
ORDER BY origin_server_ts %s
LIMIT 1;
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
"""

def get_event_for_timestamp_txn(txn) -> str:

if direction == "b":
# Find closest event *before* a given timestamp. We use descending
# (which gives values largest to smallest) because we want the
# largest possible timestamp *before* the given timestamp.
comparison_operator = "<="
order = "DESC"
else:
# Find closest event *after* a given timestamp. We use ascending
# (which gives values smallest to largest) because we want the
# closest possible timestamp *after* the given timestamp.
comparison_operator = ">="
order = "ASC"

txn.execute(
sql_template % (comparison_operator, order), (timestamp, room_id)
)
row = txn.fetchone()
logger.info("row %s", row)
if row:
(event_id,) = row
return event_id

raise SynapseError(
404,
"Unable to find event from %s in direction %s" % (timestamp, direction),
errcode=Codes.NOT_FOUND,
)

if direction not in ("f", "b"):
raise SynapseError(
400, "Unknown direction: %s" % (direction,), errcode=Codes.INVALID_PARAM
)
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved

return await self.db_pool.runInteraction(
"get_event_for_timestamp_txn",
get_event_for_timestamp_txn,
)