2019-09-17 14:55:29 +03:00
|
|
|
> **Warning**
|
|
|
|
> These architecture notes are spectacularly old, and date back
|
|
|
|
> to when Synapse was just federation code in isolation. This should be
|
|
|
|
> merged into the main spec.
|
|
|
|
|
|
|
|
# Server to Server
|
|
|
|
|
|
|
|
## Server to Server Stack
|
|
|
|
|
2021-11-16 13:21:01 +03:00
|
|
|
To use the server to server stack, homeservers should only need to
|
2019-09-17 14:55:29 +03:00
|
|
|
interact with the Messaging layer.
|
|
|
|
|
|
|
|
The server to server side of things is designed into 4 distinct layers:
|
|
|
|
|
|
|
|
1. Messaging Layer
|
|
|
|
2. Pdu Layer
|
|
|
|
3. Transaction Layer
|
|
|
|
4. Transport Layer
|
|
|
|
|
|
|
|
Where the bottom (the transport layer) is what talks to the internet via
|
|
|
|
HTTP, and the top (the messaging layer) talks to the rest of the Home
|
|
|
|
Server with a domain specific API.
|
|
|
|
|
|
|
|
1. **Messaging Layer**
|
|
|
|
|
2021-11-16 13:21:01 +03:00
|
|
|
This is what the rest of the homeserver hits to send messages, join rooms,
|
2019-09-17 14:55:29 +03:00
|
|
|
etc. It also allows you to register callbacks for when it get's notified by
|
|
|
|
lower levels that e.g. a new message has been received.
|
|
|
|
|
|
|
|
It is responsible for serializing requests to send to the data
|
|
|
|
layer, and to parse requests received from the data layer.
|
|
|
|
|
|
|
|
2. **PDU Layer**
|
|
|
|
|
|
|
|
This layer handles:
|
|
|
|
|
|
|
|
- duplicate `pdu_id`'s - i.e., it makes sure we ignore them.
|
|
|
|
- responding to requests for a given `pdu_id`
|
|
|
|
- responding to requests for all metadata for a given context (i.e. room)
|
|
|
|
- handling incoming backfill requests
|
|
|
|
|
|
|
|
So it has to parse incoming messages to discover which are metadata and
|
|
|
|
which aren't, and has to correctly clobber existing metadata where
|
|
|
|
appropriate.
|
|
|
|
|
|
|
|
For incoming PDUs, it has to check the PDUs it references to see
|
|
|
|
if we have missed any. If we have go and ask someone (another
|
2021-11-16 13:21:01 +03:00
|
|
|
homeserver) for it.
|
2019-09-17 14:55:29 +03:00
|
|
|
|
|
|
|
3. **Transaction Layer**
|
|
|
|
|
|
|
|
This layer makes incoming requests idempotent. i.e., it stores
|
|
|
|
which transaction id's we have seen and what our response were.
|
|
|
|
If we have already seen a message with the given transaction id,
|
|
|
|
we do not notify higher levels but simply respond with the
|
|
|
|
previous response.
|
|
|
|
|
|
|
|
`transaction_id` is from "`GET /send/<tx_id>/`"
|
|
|
|
|
|
|
|
It's also responsible for batching PDUs into single transaction for
|
|
|
|
sending to remote destinations, so that we only ever have one
|
|
|
|
transaction in flight to a given destination at any one time.
|
|
|
|
|
|
|
|
This is also responsible for answering requests for things after a
|
|
|
|
given set of transactions, i.e., ask for everything after 'ver' X.
|
|
|
|
|
|
|
|
4. **Transport Layer**
|
|
|
|
|
|
|
|
This is responsible for starting a HTTP server and hitting the
|
|
|
|
correct callbacks on the Transaction layer, as well as sending
|
|
|
|
both data and requests for data.
|
|
|
|
|
|
|
|
## Persistence
|
|
|
|
|
|
|
|
We persist things in a single sqlite3 database. All database queries get
|
|
|
|
run on a separate, dedicated thread. This that we only ever have one
|
|
|
|
query running at a time, making it a lot easier to do things in a safe
|
|
|
|
manner.
|
|
|
|
|
|
|
|
The queries are located in the `synapse.persistence.transactions` module,
|
|
|
|
and the table information in the `synapse.persistence.tables` module.
|