Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
Client-Server v2 Design #4
Conversation
Kegsay
and others
added some commits
Dec 22, 2014
|
Why did the list of 10 use cases at the beginning of client_server_use_cases.log get deleted? I'm not entirely sure how these use cases are intended to factor into the CS v2 API discussion, so it's a bit hard to comment. On the data-flows for forums, I'm not convinced that each thread should be a room. Instead, it's surely analogous to having multiple threads of conversations within a single room, where the room is the forum - just like on an IRC-style room. So i'd suggest we just support threading messages within a room, and possibly the ability to filter on specific thread IDs? |
Kegsay
added some commits
Dec 29, 2014
Restored. |
Kegsay
added some commits
Dec 30, 2014
|
Client capabilities will need to take into account capabilities of clients that do not have an active stream but are being pushed for events. These clients could still answer VoIP calls from a push and so their caps should advertise VoIP. However, we need to be wary of keeping stale capabilities if I install a fancy client that supports VoIP and push then decide I don't like it and uninstall it (potentially without logging out). Does everyone think I still support VoIP because that client is being pushed (even if the push is going into the void)? |
Kegsay
changed the title from
Client Design
to
Client-Server v2 Design
Jan 5, 2015
Kegsay
and others
added some commits
Jan 5, 2015
Global
|
|
Things that I think are missing here:
|
|
How are we doing delivery/read receipts? A client event per event to give feedback on? |
added some commits
Jan 5, 2015
|
The suggestion is that we could do individual receipts, but I would prefer a "read up to" marker simply for better scaling. What this looks like is not specified. Sessions time out after a short amount of time without any requests. A Web app would be listening and so be making requests. Can you provide a case where this is insufficient? Name and topic events are mainly there to say "state events". They were included because the api was derived from use cases which used name and topic. The only case where we may want to limit the kinds of state events is on public room lists which the client hasn't joined. You don't want to expose the entire room state in this case. |
Maybe we should specify it? :)
This is not the same as:
The first one (to me) means that the session is kept active and times out, the second means that we a session is grouping together a bunch of requests that happen to have been sent roughly at the same time. |
Kegsay
added some commits
Jan 6, 2015
|
When specifying the HTTP API we should prefix the URLS with "/_matrix/client/v2" rather than "/_matrix/client/api/v2" to make it consistent with the other API prefixes. |
Kegsay
and others
added some commits
Jan 6, 2015
|
We might need a few different filter options for how "relates_to" is bundled to the client.
|
|
I also continue to really dislike the fact that "relates_to" only lets you specify a single relationship between two events of the same type. Forcing that m.room.message A "relates_to" another m.room.message B means that A is a threaded conversation reply to B is needlessly restrictive. What if A and B relate to each other by some other metric (e.g. they are part of a group rather than a thread? or we distinguish mail-style threading from multithreaded-IM threading for the same set of messages? etc)? |
There is a good argument here for extending "relates_to" to include information about how the message relates to the message other than just through it's event type. I'd suggest that we extend the "relates_to" to take a list of pairs of event_ids and relationship types.
The filter API would need flags to control which relationships were and were not bundled within an event. If the mechanism was this generic would we still need a separate "updates" key? Or would "updates" become:
|
|
I like Mark's idea. For what it's worth, the issues brought up with pagination are not unique to |
Kegsay
added some commits
Jan 7, 2015
|
https://matrix.org/jira/browse/SPEC-14 should be included. We should support something akin to sticky threads / flagging messages which bing. Whether this forms part of the event JSON spec or is a flag you can give when sending a message event is debatable. |
|
surely metadata like "this msg is a notice" or "this msg is sticky/flagged" should be on the event itself - especially for mutable flags. and the api then needs to support querying on said metadata for presenting sticky msgs etc |
|
Yes it needs to be on the event, but where? If it is in the content then that means m.room.message events will need an additional key on the event content to state this, and the home server cannot enforce any rules, and it would force us to make individual keys on event content filterable. If it is a flag on the cs api then the hs could feasibly do some sanity checks and add the key on the top level of the event (like origin_server_ts). |
Content type (but it needs to be orthogonal to content type so you can have sticky image messages etc)
|
|
Hmm, you can actually enforce rules on it, just like we do for m.room.member events, so ignore me. A key on the content wfm |
|
(You can't enforce it if the content has been encrypted) |
|
|
More questions which came up whilst reviewing today:
|
Kegsay
added some commits
Jan 12, 2015
|
I have removed
Clarified as "published rooms" rather than "public rooms" to avoid confusion with the
You inspect the read-up-to marker that comes down your event stream. There's nothing special about keeping this bit of data in sync vs everything else (e.g. room member state, room name, etc). |
|
Some of the points I made earlier seem to have been missed: Comments on the general_api.rstEvent Stream API
Why? This will mean that people will see different history depending on the exact timings of their event stream, and if they are looking at it live or if they are paginating back. Just because a topic has been replaced doesn't mean I don't want to know that someone tried to change the topic just before that. The inconsistency here could lead to mass confusion if half the room see a state event and the other half don't.
These need to be local server events. Joining a room
How does this work in practice? What happens between the client getting a join event and getting the generated event? Action APIsSend a message
What are the failure modes here? The most worrying one I can currently think of is if a HTTP library only allows a max number, say 5, concurrent connections (e.g. a web browser does this). If the first PUT blackholes and 5 other requests get stuck behind it, then the retry of the original PUT gets blocked behind the requests waiting for it, the only way out of this is when one of other requests times out.
This does not need to be happen for E2E, since that only protects contents. The only time this would be useful is if a client wanted to sign the entire event for some paranoid reason. Sessions
The phrase "within a short amount of time" scares me here. What do you mean by that? Surely we want sessions to last as long as the client is being used? For a desktop app this would be hours, if not days/weeks/months.
Do we really want to be so brutal? Having to resend a request just because the server has timed us out seems like a bit of a pain. How does this work with "clients" that only want to send the odd message every now and again, and don't want to have to start sessions? In reply to (Events)
This, to me, implies that you can't display an event unless you have all of its child events. How do you know if you have them all? I think the intention with this sentence was to indicate that whenever a server tells clients about an event it always includes any child events that updated it. Things I still think are missing
|
This has already been specified. "This will be a local server event (not shared with other servers)."
This has already been marked as a problem on the send a message API: "[...]Is this even practical, given clients have a limit on the number of concurrent connections? [...]" and Action IDs: "Blocking requests with higher seqnums is troublesome if there is a max # of concurrent connections a client can have open."
I responded to this in the comments of this PR, and clarified the meaning of this in a later commit: "[...]Sessions time out after a short amount of time without any requests.[...]"
I have already added this feedback as a known issue in the Action IDs section: "Session expiry: Do we really have to fonx the request if it was done with an old session ID?"
What specifically is missing? It's mentioned that servers can send events. Some server-generated events are even specified e.g.
This has already been specified in the "Unknown rooms" section of the event stream API. As for the bits I have not addressed:
I'll tweak the phrasing of this.
What's the use case here? The session ID is just returned in response to the first request made without a session ID, so I don't really see the problem here.
Is there any reason to have multi-stage signing then, or can I nuke that entirely?
Can you provide an alternative which doesn't place unreasonable requirements on the client? The best alternative I can think of is giving the clobbered event then sending the current state again immediately after it (which still creates an inconsistent state since history is wrong). I think this is a compromise we need to make for eventual consistency.
This is mainly for the benefit of other devices. If a device performs the join, they will get a chunk of events in response to the join, along with a token so they aren't blocked going into the next screen. For other devices however, they will just begin getting events for a new room they joined, without a chunk token to scrollback if desired. This is the use case we're trying to resolve here (which isn't clear at all in the doc; will clarify). There isn't anything of interest between the join and the server-generated event, it just means other devices won't be able to scrollback until they get it. |
|
Okay, cool. It looks like I missed a lot of these things because they were addressed in different places than where I noted the problems.
I still think the statement "A session is a group of requests sent within a short amount of time by the same client." is completely misleading/wrong, and the clarification doesn't contradict this.
I guess mostly what they look like and how they behave. Are they just like regular events? How do you tell a normal event from a server local one? Can they be sent? What about EDU style ones? E.g. for server status notifications. Some of this should probably go into use cases I guess.
The use case is for automatic scripts that want to send a message to a room in the simplest way. E.g. like all the various automatic IRC notices we have. I guess its probably fine so long as bots don't /have/ to remember session ids. Why do clients need to store session ids? Can that not be done purely server side?
Stick an extra flag on a state event to indicate whether it should clobber existing state or not?
My worry here is that a client will have to wait between a "join" event and another server generated event. It's always annoying from a client and what goes wrong perspective if we have to wait asynchronously for something before we can process it. Unless I'm misunderstanding what is happening? |
|
Also: Invites should probably include some information about the room other than the room id and who invited you. What should these things be? Name, topic, member lists? Should it also include a "reason" field so that people can give a reason for the invite? |
Kegsay
added some commits
Jan 12, 2015
This is an interesting point. The client needs to know its session so it can reset its action ID when it starts a new session. It may be easier to say "if you get back a 'reset action ID' flag on your request, then reset your action IDs". The concept of a session would still be present, but the boilerplate of having to send it on every request would be avoided. This needs some input from Mark.
That, combined with being an "out-of-order" event (so it can be inserted into the right place in the message history screen) could possibly work. It's an annoying extra check which needs to be done for every state event ever though, but I suppose if it only comes down with the "out of order" flag set then this could actually work.
You have the right idea. My counter to that was simply along the lines that "given this device was not the one that triggered the action, it is unlikely that they will require that data immediately, so relying on the async response is acceptable." As I said before, this does not apply to the device which clicked through to the room, since they got all the data they needed in response to the request.
I've marked these notes on the Invite API and brought it down to |
ara4n
added some commits
Jan 13, 2015
|
Erik, Mark, Dave and I had a discussion on the concept of Sessions/Action IDs to try to unblock some of the problems raised. General notes from this are below: Sending messagesProblems trying to solve:
Original proposal:
Problems raised with original proposal:
Why ordering is Hard:
Proposed solution:
SessionsThe session concept was designed to combine APIs which could "time out" through network connectivity losses. The idea was that there would be a single timer which could detect if they were connected or not. In practice, this combined the typing timeout and the presence timeout (which in v1 is implicitly linked to the event stream). Problems:
Typing We propose splitting out the typing part of Sessions to be as v1 does it. The assumption here is that there isn't going to be lots of client timers repoking the server saying they are still typing, given that you'll on average have 1 room set to typing per user. This makes understanding timers for typing easier to understand. Presence We would prefer to not have to keep repoking the server to say the client is alive, when we are already implicitly doing this via the event stream. We also want a way to "appear offline" whilst still making requests. We propose swapping the concept of a "session" which is determined by the server with a concept of a "launch-id" which is determined by the client. A "launch-id" of a client is the period in which a client will be persisting EDU-like data (e.g. presence, typing). For mobile devices, this is set when the app launches (hence the term), and a new launch ID is generated whenever the app is relaunched from cold. With this new concept, we propose coupling more explicitly the relationship between launch-ids, presence and the event stream. This involves adding 2 new flags to the event stream:
If the client goes into a long tunnel, the server may time out the launch ID. A timed out launch ID results in presence going to offline.When the client exits the tunnel, the repoll will either fail outright (e.g. 4xx), or return a response with something in the body to say "hey, I no longer recognise this launch ID". When the client receives this, they need to regenerate the launch ID: Launch IDs are scoped to a device ID / user ID combo (e.g. This API covers the "appear offline" use case (simply don't Summary
|
ara4n
and others
added some commits
Jan 14, 2015
|
Revised notes on Presence:
|
Kegsay commentedDec 22, 2014
Contains use cases, data flows and a general API for CS v2.
General API:
https://github.com/matrix-org/matrix-doc/blob/use-cases/drafts/general_api.rst
HTTP API:
https://github.com/matrix-org/matrix-doc/blob/use-cases/drafts/cs-v2-http-api.rst