make `future_group_id` server generated and small adjustments

toger5/expiring-events-keep-alive
Timo 2 years ago
parent 1140ce9fe5
commit 0a7896e92c

@ -65,30 +65,43 @@ the users has left the call.
This proposal also includes a way to refresh the timeout. Allowing to delay the event multiple times.
A periodic ping of the refreshing can be used as a heardbeat mechanism. Once the refresh ping is not send
anymore the timeout conditino is met and the homerver sends the event with the expired content information.
anymore the timeout condition is met and the homerver sends the event with the expired content information.
This translate to: _"only send the event when the client is not running the its program anymore (not sending the heartbeat anymore)"_
We call those delayed events `Futures`.
New endpoints are introduced:
`PUT /_matrix/client/v3/rooms/{roomId}/send_future/{txnId}?timeout={timeout_duration}&future_group_id={group_id}`
`PUT /_matrix/client/v3/rooms/{roomId}/send_future/{eventType}/{txnId}?future_timeout={timeout_duration}&future_group_id={group_id}`
`PUT /_matrix/client/v3/rooms/{roomId}/state_future/{eventType}/{stateKey}?timeout={timeout_duration}&future_group_id={group_id}`
`PUT /_matrix/client/v3/rooms/{roomId}/state_future/{eventType}/{stateKey}?future_timeout={timeout_duration}&future_group_id={group_id}`
Those behave like the normal `send`/`state` endpoints except that that they allow
to define a `timeout` and a `future_group_id` in their query parameters.
The **`future_group_id`** is an identifier defined by the client.
The purpose of this identifier is to group multiple futures in one mutually exclusive group.
Only one of the events in such a group can ever reach the DAG/will be distributed by the homeserver.
All other events will be discarded.
One group can only contain one event with a `timeout` (timeout futures). The other events do not have a timeout (action futures) and are send
as an mutually exclusive alternative to the event send with `timeout`.
We call these timeout futures and action futures.
The server will respond with a [`409`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409)
(`Conflict` This response is sent when a request conflicts with the current state of the server.) if
the client tries to send an action future without there being a timeout future with the same `group_id`
to define `future_timeout` and `future_group_id` in their query parameters.
- `future_timeout: number | "none"` is a required parameter that defines how long the homeserver will wait before sending
the event into the room. Since the timeout can be refreshed and sending the future can be triggered via an endpoint (see: [Proposal/Delegating futures](#delegating-futures)) this value is not enough to predict the time this event will arrive in the room.
- If set to `"none"` the future will never expire and can only be send by the [external delegation endpoint](#delegating-futures).
We call such a future **action future**.
- If set to a `number` we call the future **timeout future**
- `future_group_id: string` is optional if a `future_timeout` is a `number`. The purpose of this identifier is to group
**multiple futures in one mutually exclusive group**.
- Only one of the events in such a group can ever reach the DAG/will be distributed by the homeserver.
All other futures will be discarded.
- Every future group needs at least one timeout future to guarantee that all future expire eventually.
- If a timeout future is send without a `future_group_id` a unique identifier will be generated by the
homeserver and is part of the `send_future`response.
Possible error responses are all error responses that can occur when using the `send` and `state` endpoint accordingly and:
- The server will respond with a [`409`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409)
(`Conflict` This response is sent when a request conflicts with the current state of the server.) if
the client tries to send an action future without there being a timeout future with the same `future_group_id`
- The server can optionally configure a maximum `timeout_duration`
(In the order of one week dependent on how long they want to track futures)
The server will respond with a [`400`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400) (`Bad Request`, with a message
containing the maximum allowed `timeout_duration`) if the
client tries to send a timeout future with a larger `timeout_duration`.
The body is the same as sending a normal event.
@ -106,6 +119,7 @@ The response will include a `send_token` and a optional `refresh_token` but no `
// always present
"send_token": "token",
// optional if there is a timeout
"future_group_id": "group_id",
"refresh_token": "token",
"cancel_token": "token"
}
@ -125,18 +139,18 @@ This unauthenticated endpoint allows to delegate resolving the future.
An SFU for instance, that tracks the current client connection state, could get a url that it
needs to call every X hours while a user is connected and a url it has to call once the user disconnects.
This way the SFU can be used as the source of truth for the call member room state even if the client
gets closed or looses connection and without knowing anything about the matrix call.
gets closed or looses connection and without knowing anything about the Matrix call.
The homeserver does the following when receiving a Future:
- It checks for the validity of the request (based on the `timeout` and the `group_id` query parameters)
and returns a `409` if necessary.
- It **generates** a `send_token` and optionally a `refresh_token`, `cancel_token` and stores them alongside the time
of retrieval, the `group_id` and the `timeout_duration`.
- If `timeout` was present, it **Starts a timer** for the `refresh_token`.
- It checks for the validity of the request (based on the `future_timeout` and the `future_group_id` query parameters)
and returns a `409` or `400` if necessary.
- It **generates** a `send_token` and optionally a `future_group_id`, a `refresh_token` and a `cancel_token` and stores them alongside the time
of retrieval and the `timeout_duration`.
- If `future_timeout` was present, it **Starts a timer** for the `refresh_token`.
- If a `PUT /_matrix/client/v3/futures/{refresh_token}` is received, it
**restarts the timer** with the stored timeout duration for the associated timeout future.
**restarts the timer** with the stored `timeout_duration` for the associated timeout future.
- If a `PUT /_matrix/client/v3/futures/{send_token}` is received, it **sends the associated action or timeout future**
and deletes any stored futures with the `group_id` associated with that token.
- If a `PUT /_matrix/client/v3/futures/{cancel_token}` is received, it **does NOT send any future**
@ -154,14 +168,14 @@ The homeserver does the following when receiving a Future:
- After the homeservers sends a timeout future or action future, the associated
timer and tokens is canceled/deleted.
So for each `group_id` the client sends, the homeserver will send one event
conditionally at an unknown time that can trigger logic on the client or
no event if the `/_matrix/client/v3/futures/{cancel_token}` was called.
So for each `future_group_id`, the homeserver will at most send one timeline event.
This allows for any generic timeout logic.
- No timeline event will be send in case all of the timeout futures in a future group are cancelled via `/_matrix/client/v3/futures/{cancel_token}`.
- Otherwise one of the timeout or action future will be emitted.
Timed messages/reminders or ephemeral events could be implemented using this where
clients send a redact as a future or a room event with intentional mentions.
Timed messages, tea timers, reminders or ephemeral events could be implemented
using this where clients send room events with
intentional mentions or a redaction as a future.
In some scenarios it is important to allow to send an event with an associated
future at the same time.
@ -177,8 +191,11 @@ future at the same time.
For this usecase batch sending of multiple futures would be desired.
We do not include batch sending in this MSC however since batch sending should
become a generic matrix concept as proposed with `/send_pdus`. (see: [MSC4080: Cryptographic Identities](https://github.com/matrix-org/matrix-spec-proposals/pull/4080))
We do not include batch sending in the proposal of this MSC however since batch sending should
become a generic Matrix concept as proposed with `/send_pdus`. (see: [MSC4080: Cryptographic Identities](https://github.com/matrix-org/matrix-spec-proposals/pull/4080))
There is a [batch sending version](#batch-sending-futures-with-custom-endpoint) in the Alternatives section
that proposes a future specific group sending endpoint in case this is required sooner then its realistic to implement [MSC4080: Cryptographic Identities](https://github.com/matrix-org/matrix-spec-proposals/pull/4080).
### Getting running futures
@ -189,7 +206,7 @@ of the final event content with the associated tokens.
```json
[
{
"url":"https://domain/_matrix/client/v3/futures/{refresh_token}",
"url":"/_matrix/client/v3/rooms/{roomId}/send_future/{eventType}/{txnId}?timeout={timeout_duration}&future_group_id={group_id}",
"body":{
...event_body
},
@ -197,8 +214,9 @@ of the final event content with the associated tokens.
// always present
"send_token": "token",
// optional if there is a timeout
"future_group_id": "group_id",
"refresh_token": "token",
"cancel_token": "token"
"cancel_token": "token",
}
},
]
@ -206,7 +224,7 @@ of the final event content with the associated tokens.
This can be used so clients can optionally display events
that will be send in the future.
And to optionally cancel tokens for them.
And to acquire cancel_tokens for then.
For all usecases where the existence of a running future is also of interest for other room members,
(like self-destructing messages) it is recommended to include
@ -221,7 +239,7 @@ and alternative expiration systems are evaluated.
#### Background
MatrixRTC makes it necessary to have real time information about the current matrixRTC session.
MatrixRTC makes it necessary to have real time information about the current MatrixRTC session.
To properly display room tiles and header in the room list (or compute a list of ongoing calls) need to know:
- If there is a running session.
@ -245,7 +263,7 @@ Example:
> A room list with 100 rooms where there has been a call before in every room (or there is an ongoing call) would require the client to send a to-device message (or a request to the SFU) to every user that has an active state event to check if they are still online. Just to display the room tile properly.
For displaying the room list timeout based approaches are much more reasonable because this allows computing matrixRTC metadata for a room to be synchronous.
For displaying the room list timeout based approaches are much more reasonable because this allows computing MatrixRTC metadata for a room to be synchronous.
The current solution updates the room state every X minutes. This is not elegant since we basically resend room state with the same content. In large calls this could result in huge traffic/large DAGs (100 call members implies 100 state events every X minutes.) X cannot be a long duration because it is the duration after which we can consider the event as expired. Improper disconnects would result in the user being displayed as "still in the call" for X minutes (we want this to be as short as possible!)
@ -270,7 +288,7 @@ With this proposal we can provide an elegant solution using actions and timeouts
This MSC also allows to implement self-destructing messages:
First send (or generate the pdu when [MSC4080: Cryptographic Identities](https://github.com/matrix-org/matrix-spec-proposals/pull/4080) is available):
`PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`
`PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{eventType}/{txnId}`
```json
{
@ -279,7 +297,7 @@ First send (or generate the pdu when [MSC4080: Cryptographic Identities](https:/
```
then send:
`PUT /_matrix/client/v3/rooms/{roomId}/send_future/{txnId}?timeout={10*60}&future_group_id={XYZ}`
`PUT /_matrix/client/v3/rooms/{roomId}/send_future/{eventType}/{txnId}?timeout={10*60}&future_group_id={XYZ}`
```json
{
@ -297,10 +315,10 @@ This would redact the message with content: `"m.text": "my msg"` after 10minutes
Since the `send_future` and `state_future` endpoints are almost identical to the
normal `send` and `state` endpoints it comes to mind, that one could reuse them and allow adding the
query parameters `?timeout={timeout_duration}&future_group_id={group_id}` directly to the
query parameters `?future_timeout={timeout_duration}&future_group_id={group_id}` directly to the
`send` and `state` endpoint.
This would be elegant but since those two endpoint are core to matrix changes to them might
This would be elegant but since those two endpoint are core to Matrix changes to them might
be controversion if their return value is altered.
Currently they always return
@ -326,6 +344,7 @@ As a result the return type would change to:
```json
{
"event_id": string | undefined,
"future_group_id": string | undefined,
"send_token": string | undefined,
"refresh_token": string | undefined,
"cancel_token": "string | undefined
@ -337,18 +356,19 @@ dependent on the query parameters.
### Batch sending futures with custom endpoint
The proposed solution does not allow to send multiple events/futures that belong to each other with one
HTTPS request. This is desired for self-destructing events and for matrixRTC room state events, where
HTTPS request. This is desired for self-destructing events and for MatrixRTC room state events, where
we want the guarantee, that the event itself and the future removing the event both reach the homeserver
with one request. Otherwise there is a rist for the client to loose connecting or crash between sending the
event and the future which results in never expiring call memberhsip or never destructing self-destructing messages.
This would be solved once [MSC4080](https://github.com/matrix-org/matrix-spec-proposals/pull/4080) and the `/send_pdus` endpoint is implemented.
(Then the `timeout` and `future_group_id` could be added
(Then the `future_timeout` and `future_group_id` could be added
to the `PDUInfo` instead of the query parameters and everything could be send at once.)
This would be the preferred solution since we currently don't have any other batch sending mechanism.
before
It would however require lots of changes since a new widget action for futures would be needed.
With the current main proposal it is enough to add a timeout parameter to the send message widget action.
With the current main proposal it is enough to add a `future_timeout` and `future_group_id` parameter to the send message widget action.
The widget driver would then take care of calling `send` or `send_future` based on the presence of those fields.
An alternative to the proposed solution that allows this kind of batch sending would be to
introduce this endpoint:
@ -412,6 +432,8 @@ The response will be a collection of all the futures with the same fields as in
}
```
We do not need a `future_group_id` since we will send one group in one request.
Working with futures is the same with this alternative.
This means,

Loading…
Cancel
Save