This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add admin API to get some information about federation status (#11407)
- Loading branch information
Showing
7 changed files
with
783 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add admin API to get some information about federation status with remote servers. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# Federation API | ||
|
||
This API allows a server administrator to manage Synapse's federation with other homeservers. | ||
|
||
Note: This API is new, experimental and "subject to change". | ||
|
||
## List of destinations | ||
|
||
This API gets the current destination retry timing info for all remote servers. | ||
|
||
The list contains all the servers with which the server federates, | ||
regardless of whether an error occurred or not. | ||
If an error occurs, it may take up to 20 minutes for the error to be displayed here, | ||
as a complete retry must have failed. | ||
|
||
The API is: | ||
|
||
A standard request with no filtering: | ||
|
||
``` | ||
GET /_synapse/admin/v1/federation/destinations | ||
``` | ||
|
||
A response body like the following is returned: | ||
|
||
```json | ||
{ | ||
"destinations":[ | ||
{ | ||
"destination": "matrix.org", | ||
"retry_last_ts": 1557332397936, | ||
"retry_interval": 3000000, | ||
"failure_ts": 1557329397936, | ||
"last_successful_stream_ordering": null | ||
} | ||
], | ||
"total": 1 | ||
} | ||
``` | ||
|
||
To paginate, check for `next_token` and if present, call the endpoint again | ||
with `from` set to the value of `next_token`. This will return a new page. | ||
|
||
If the endpoint does not return a `next_token` then there are no more destinations | ||
to paginate through. | ||
|
||
**Parameters** | ||
|
||
The following query parameters are available: | ||
|
||
- `from` - Offset in the returned list. Defaults to `0`. | ||
- `limit` - Maximum amount of destinations to return. Defaults to `100`. | ||
- `order_by` - The method in which to sort the returned list of destinations. | ||
Valid values are: | ||
- `destination` - Destinations are ordered alphabetically by remote server name. | ||
This is the default. | ||
- `retry_last_ts` - Destinations are ordered by time of last retry attempt in ms. | ||
- `retry_interval` - Destinations are ordered by how long until next retry in ms. | ||
- `failure_ts` - Destinations are ordered by when the server started failing in ms. | ||
- `last_successful_stream_ordering` - Destinations are ordered by the stream ordering | ||
of the most recent successfully-sent PDU. | ||
- `dir` - Direction of room order. Either `f` for forwards or `b` for backwards. Setting | ||
this value to `b` will reverse the above sort order. Defaults to `f`. | ||
|
||
*Caution:* The database only has an index on the column `destination`. | ||
This means that if a different sort order is used, | ||
this can cause a large load on the database, especially for large environments. | ||
|
||
**Response** | ||
|
||
The following fields are returned in the JSON response body: | ||
|
||
- `destinations` - An array of objects, each containing information about a destination. | ||
Destination objects contain the following fields: | ||
- `destination` - string - Name of the remote server to federate. | ||
- `retry_last_ts` - integer - The last time Synapse tried and failed to reach the | ||
remote server, in ms. This is `0` if the last attempt to communicate with the | ||
remote server was successful. | ||
- `retry_interval` - integer - How long since the last time Synapse tried to reach | ||
the remote server before trying again, in ms. This is `0` if no further retrying occuring. | ||
- `failure_ts` - nullable integer - The first time Synapse tried and failed to reach the | ||
remote server, in ms. This is `null` if communication with the remote server has never failed. | ||
- `last_successful_stream_ordering` - nullable integer - The stream ordering of the most | ||
recent successfully-sent [PDU](understanding_synapse_through_grafana_graphs.md#federation) | ||
to this destination, or `null` if this information has not been tracked yet. | ||
- `next_token`: string representing a positive integer - Indication for pagination. See above. | ||
- `total` - integer - Total number of destinations. | ||
|
||
# Destination Details API | ||
|
||
This API gets the retry timing info for a specific remote server. | ||
|
||
The API is: | ||
|
||
``` | ||
GET /_synapse/admin/v1/federation/destinations/<destination> | ||
``` | ||
|
||
A response body like the following is returned: | ||
|
||
```json | ||
{ | ||
"destination": "matrix.org", | ||
"retry_last_ts": 1557332397936, | ||
"retry_interval": 3000000, | ||
"failure_ts": 1557329397936, | ||
"last_successful_stream_ordering": null | ||
} | ||
``` | ||
|
||
**Response** | ||
|
||
The response fields are the same like in the `destinations` array in | ||
[List of destinations](#list-of-destinations) response. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
# Copyright 2021 The Matrix.org Foundation C.I.C. | ||
# | ||
# 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. | ||
import logging | ||
from http import HTTPStatus | ||
from typing import TYPE_CHECKING, Tuple | ||
|
||
from synapse.api.errors import Codes, NotFoundError, SynapseError | ||
from synapse.http.servlet import RestServlet, parse_integer, parse_string | ||
from synapse.http.site import SynapseRequest | ||
from synapse.rest.admin._base import admin_patterns, assert_requester_is_admin | ||
from synapse.storage.databases.main.transactions import DestinationSortOrder | ||
from synapse.types import JsonDict | ||
|
||
if TYPE_CHECKING: | ||
from synapse.server import HomeServer | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ListDestinationsRestServlet(RestServlet): | ||
"""Get request to list all destinations. | ||
This needs user to have administrator access in Synapse. | ||
GET /_synapse/admin/v1/federation/destinations?from=0&limit=10 | ||
returns: | ||
200 OK with list of destinations if success otherwise an error. | ||
The parameters `from` and `limit` are required only for pagination. | ||
By default, a `limit` of 100 is used. | ||
The parameter `destination` can be used to filter by destination. | ||
The parameter `order_by` can be used to order the result. | ||
""" | ||
|
||
PATTERNS = admin_patterns("/federation/destinations$") | ||
|
||
def __init__(self, hs: "HomeServer"): | ||
self._auth = hs.get_auth() | ||
self._store = hs.get_datastore() | ||
|
||
async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]: | ||
await assert_requester_is_admin(self._auth, request) | ||
|
||
start = parse_integer(request, "from", default=0) | ||
limit = parse_integer(request, "limit", default=100) | ||
|
||
if start < 0: | ||
raise SynapseError( | ||
HTTPStatus.BAD_REQUEST, | ||
"Query parameter from must be a string representing a positive integer.", | ||
errcode=Codes.INVALID_PARAM, | ||
) | ||
|
||
if limit < 0: | ||
raise SynapseError( | ||
HTTPStatus.BAD_REQUEST, | ||
"Query parameter limit must be a string representing a positive integer.", | ||
errcode=Codes.INVALID_PARAM, | ||
) | ||
|
||
destination = parse_string(request, "destination") | ||
|
||
order_by = parse_string( | ||
request, | ||
"order_by", | ||
default=DestinationSortOrder.DESTINATION.value, | ||
allowed_values=[dest.value for dest in DestinationSortOrder], | ||
) | ||
|
||
direction = parse_string(request, "dir", default="f", allowed_values=("f", "b")) | ||
|
||
destinations, total = await self._store.get_destinations_paginate( | ||
start, limit, destination, order_by, direction | ||
) | ||
response = {"destinations": destinations, "total": total} | ||
if (start + limit) < total: | ||
response["next_token"] = str(start + len(destinations)) | ||
|
||
return HTTPStatus.OK, response | ||
|
||
|
||
class DestinationsRestServlet(RestServlet): | ||
"""Get details of a destination. | ||
This needs user to have administrator access in Synapse. | ||
GET /_synapse/admin/v1/federation/destinations/<destination> | ||
returns: | ||
200 OK with details of a destination if success otherwise an error. | ||
""" | ||
|
||
PATTERNS = admin_patterns("/federation/destinations/(?P<destination>[^/]+)$") | ||
|
||
def __init__(self, hs: "HomeServer"): | ||
self._auth = hs.get_auth() | ||
self._store = hs.get_datastore() | ||
|
||
async def on_GET( | ||
self, request: SynapseRequest, destination: str | ||
) -> Tuple[int, JsonDict]: | ||
await assert_requester_is_admin(self._auth, request) | ||
|
||
destination_retry_timings = await self._store.get_destination_retry_timings( | ||
destination | ||
) | ||
|
||
if not destination_retry_timings: | ||
raise NotFoundError("Unknown destination") | ||
|
||
last_successful_stream_ordering = ( | ||
await self._store.get_destination_last_successful_stream_ordering( | ||
destination | ||
) | ||
) | ||
|
||
response = { | ||
"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, | ||
} | ||
|
||
return HTTPStatus.OK, response |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.