mirror of
https://github.com/element-hq/synapse
synced 2024-08-15 03:40:52 +00:00
Fix get federation status of destination if no error occured (#11593)
This commit is contained in:
parent
d8f94eeec2
commit
3b51c763ba
4 changed files with 88 additions and 25 deletions
1
changelog.d/11593.bugfix
Normal file
1
changelog.d/11593.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix an error in to get federation status of a destination server even if no error has occurred. This admin API was new introduced in Synapse 1.49.0.
|
|
@ -111,25 +111,37 @@ class DestinationsRestServlet(RestServlet):
|
||||||
) -> Tuple[int, JsonDict]:
|
) -> Tuple[int, JsonDict]:
|
||||||
await assert_requester_is_admin(self._auth, request)
|
await assert_requester_is_admin(self._auth, request)
|
||||||
|
|
||||||
|
if not await self._store.is_destination_known(destination):
|
||||||
|
raise NotFoundError("Unknown destination")
|
||||||
|
|
||||||
destination_retry_timings = await self._store.get_destination_retry_timings(
|
destination_retry_timings = await self._store.get_destination_retry_timings(
|
||||||
destination
|
destination
|
||||||
)
|
)
|
||||||
|
|
||||||
if not destination_retry_timings:
|
|
||||||
raise NotFoundError("Unknown destination")
|
|
||||||
|
|
||||||
last_successful_stream_ordering = (
|
last_successful_stream_ordering = (
|
||||||
await self._store.get_destination_last_successful_stream_ordering(
|
await self._store.get_destination_last_successful_stream_ordering(
|
||||||
destination
|
destination
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
response = {
|
response: JsonDict = {
|
||||||
"destination": destination,
|
"destination": destination,
|
||||||
"failure_ts": destination_retry_timings.failure_ts,
|
|
||||||
"retry_last_ts": destination_retry_timings.retry_last_ts,
|
|
||||||
"retry_interval": destination_retry_timings.retry_interval,
|
|
||||||
"last_successful_stream_ordering": last_successful_stream_ordering,
|
"last_successful_stream_ordering": last_successful_stream_ordering,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if destination_retry_timings:
|
||||||
|
response = {
|
||||||
|
**response,
|
||||||
|
"failure_ts": destination_retry_timings.failure_ts,
|
||||||
|
"retry_last_ts": destination_retry_timings.retry_last_ts,
|
||||||
|
"retry_interval": destination_retry_timings.retry_interval,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
response = {
|
||||||
|
**response,
|
||||||
|
"failure_ts": None,
|
||||||
|
"retry_last_ts": 0,
|
||||||
|
"retry_interval": 0,
|
||||||
|
}
|
||||||
|
|
||||||
return HTTPStatus.OK, response
|
return HTTPStatus.OK, response
|
||||||
|
|
|
@ -560,3 +560,14 @@ class TransactionWorkerStore(CacheInvalidationWorkerStore):
|
||||||
return await self.db_pool.runInteraction(
|
return await self.db_pool.runInteraction(
|
||||||
"get_destinations_paginate_txn", get_destinations_paginate_txn
|
"get_destinations_paginate_txn", get_destinations_paginate_txn
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def is_destination_known(self, destination: str) -> bool:
|
||||||
|
"""Check if a destination is known to the server."""
|
||||||
|
result = await self.db_pool.simple_select_one_onecol(
|
||||||
|
table="destinations",
|
||||||
|
keyvalues={"destination": destination},
|
||||||
|
retcol="1",
|
||||||
|
allow_none=True,
|
||||||
|
desc="is_destination_known",
|
||||||
|
)
|
||||||
|
return bool(result)
|
||||||
|
|
|
@ -314,15 +314,12 @@ class FederationTestCase(unittest.HomeserverTestCase):
|
||||||
retry_interval,
|
retry_interval,
|
||||||
last_successful_stream_ordering,
|
last_successful_stream_ordering,
|
||||||
) in dest:
|
) in dest:
|
||||||
self.get_success(
|
self._create_destination(
|
||||||
self.store.set_destination_retry_timings(
|
destination,
|
||||||
destination, failure_ts, retry_last_ts, retry_interval
|
failure_ts,
|
||||||
)
|
retry_last_ts,
|
||||||
)
|
retry_interval,
|
||||||
self.get_success(
|
last_successful_stream_ordering,
|
||||||
self.store.set_destination_last_successful_stream_ordering(
|
|
||||||
destination, last_successful_stream_ordering
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# order by default (destination)
|
# order by default (destination)
|
||||||
|
@ -413,11 +410,9 @@ class FederationTestCase(unittest.HomeserverTestCase):
|
||||||
_search_test(None, "foo")
|
_search_test(None, "foo")
|
||||||
_search_test(None, "bar")
|
_search_test(None, "bar")
|
||||||
|
|
||||||
def test_get_single_destination(self) -> None:
|
def test_get_single_destination_with_retry_timings(self) -> None:
|
||||||
"""
|
"""Get one specific destination which has retry timings."""
|
||||||
Get one specific destinations.
|
self._create_destinations(1)
|
||||||
"""
|
|
||||||
self._create_destinations(5)
|
|
||||||
|
|
||||||
channel = self.make_request(
|
channel = self.make_request(
|
||||||
"GET",
|
"GET",
|
||||||
|
@ -432,6 +427,53 @@ class FederationTestCase(unittest.HomeserverTestCase):
|
||||||
# convert channel.json_body into a List
|
# convert channel.json_body into a List
|
||||||
self._check_fields([channel.json_body])
|
self._check_fields([channel.json_body])
|
||||||
|
|
||||||
|
def test_get_single_destination_no_retry_timings(self) -> None:
|
||||||
|
"""Get one specific destination which has no retry timings."""
|
||||||
|
self._create_destination("sub0.example.com")
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
self.url + "/sub0.example.com",
|
||||||
|
access_token=self.admin_user_tok,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(HTTPStatus.OK, channel.code, msg=channel.json_body)
|
||||||
|
self.assertEqual("sub0.example.com", channel.json_body["destination"])
|
||||||
|
self.assertEqual(0, channel.json_body["retry_last_ts"])
|
||||||
|
self.assertEqual(0, channel.json_body["retry_interval"])
|
||||||
|
self.assertIsNone(channel.json_body["failure_ts"])
|
||||||
|
self.assertIsNone(channel.json_body["last_successful_stream_ordering"])
|
||||||
|
|
||||||
|
def _create_destination(
|
||||||
|
self,
|
||||||
|
destination: str,
|
||||||
|
failure_ts: Optional[int] = None,
|
||||||
|
retry_last_ts: int = 0,
|
||||||
|
retry_interval: int = 0,
|
||||||
|
last_successful_stream_ordering: Optional[int] = None,
|
||||||
|
) -> None:
|
||||||
|
"""Create one specific destination
|
||||||
|
|
||||||
|
Args:
|
||||||
|
destination: the destination we have successfully sent to
|
||||||
|
failure_ts: when the server started failing (ms since epoch)
|
||||||
|
retry_last_ts: time of last retry attempt in unix epoch ms
|
||||||
|
retry_interval: how long until next retry in ms
|
||||||
|
last_successful_stream_ordering: the stream_ordering of the most
|
||||||
|
recent successfully-sent PDU
|
||||||
|
"""
|
||||||
|
self.get_success(
|
||||||
|
self.store.set_destination_retry_timings(
|
||||||
|
destination, failure_ts, retry_last_ts, retry_interval
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if last_successful_stream_ordering is not None:
|
||||||
|
self.get_success(
|
||||||
|
self.store.set_destination_last_successful_stream_ordering(
|
||||||
|
destination, last_successful_stream_ordering
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def _create_destinations(self, number_destinations: int) -> None:
|
def _create_destinations(self, number_destinations: int) -> None:
|
||||||
"""Create a number of destinations
|
"""Create a number of destinations
|
||||||
|
|
||||||
|
@ -440,10 +482,7 @@ class FederationTestCase(unittest.HomeserverTestCase):
|
||||||
"""
|
"""
|
||||||
for i in range(0, number_destinations):
|
for i in range(0, number_destinations):
|
||||||
dest = f"sub{i}.example.com"
|
dest = f"sub{i}.example.com"
|
||||||
self.get_success(self.store.set_destination_retry_timings(dest, 50, 50, 50))
|
self._create_destination(dest, 50, 50, 50, 100)
|
||||||
self.get_success(
|
|
||||||
self.store.set_destination_last_successful_stream_ordering(dest, 100)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_fields(self, content: List[JsonDict]) -> None:
|
def _check_fields(self, content: List[JsonDict]) -> None:
|
||||||
"""Checks that the expected destination attributes are present in content
|
"""Checks that the expected destination attributes are present in content
|
||||||
|
|
Loading…
Reference in a new issue