# Room Data MSC ## Problem We currently don't have a way to add data to a room and easily find it again without putting it into the state. State is a bad decision for data which is not necessary to understand the room, for example information about which messages belong to which thread. State is also bad because it's hard to group similar data together and add to or list a group. ## Proposal A new binary tree structure is introduced called "room data". It is updated by sending specific PDUs into the room and can be queried using a few new endpoints. Servers can ask each other for room data over federation if they know they are missing data, but they can't expect to have the same room data as other servers, so room data should only be used if unreliability is not fatal. The room data binary tree is made up of a key and a value. The key is made up of a valid utf-8 string, with the exception that the byte 0xff may also be used to separate parts of the key. The value is a valid utf-8 string. To avoid two servers writing to the same room data entry at the same time, all keys must end in the userid of the user that created them. For simplicity, there is no way to delete data from room data for now. New endpoints: - GET /_matrix/client/r0/rooms/{roomId}/data/get/{key} Returns the value of this specific key or 404 if it doesn't exist (TODO: flag to ask over federation?) - TODO: maybe an endpoint to query multiple keys at once? - GET /_matrix/client/r0/rooms/{roomId}/data/prefix/{prefix} Returns all (key, value) pairs where the key starts with the prefix up to a limit (TODO: flag for the limit?, flag to ask over federation?, pagination?) To add new room data, a new message event type is introduced called m.room.data with two content keys called "key" and "value", where key is required and value is not. It's also possible that other events trigger a room data addition, like m.room.message with the "in_thread" field. # Threads MSC (requires room data MSC) ## Example Imagine one project, they want to develop a game. The team started out small so they created one room and started programming. Soon they noticed that many people were talking at the same time and it was getting out of hand, so they started a new "Named Thread" called Server and one called Client. Matrix clients then hide all messages from these threads except for a small indicator to show that the threads exist and are active. There's also an option to see all threads. All users can still talk in the main room, but client or server specific discussions happens in the respective threads. Wrongly sent events can easily be moved to where they belong. One day, the client thread became very busy with lots of small discussions, all not worth their own Named Thread, so sometimes people created Unnamed Threads to work on a small feature together. While they could also do so in a private chat, doing it in unnamed threads means other people can join in and the history of the thread is perserved, even after the thread is "hidden" in a few days. ## WIP Proposal Threads are nothing more than collections of messages as opposed to their own rooms. This avoids the problem of syncing membership and other state between the main room and the threads. All users are able to create new threads and threads link to messages instead of copying/moving them, so some messages might be in multiple threads at the same time. The collections of messages are saved using room data with a "thread<0xff>" prefix followed by a thread id (usually determined by the server) and <0xff> followed by "event<0xff>" followed by an event id. The value is ignored and should be empty. Example: To add a message with event id \$abc to thread "xyz", the room data key value pair would look like this: ("thread<0xff>xyz<0xff>event<0xff>$abc", ""). Clients can get a list of all events in this thread by calling /data/prefix/thread<0xff>xyz<0xff>event<0xff> A thread can be named using a room data entry in the key "thread<0xff>xyz<0xff>name" with the name as the value. New endpoints: - TODO: create new thread - TODO: /messages for threads (doing a prefix search internally) ## Drawbacks Clients that call /sync still receive messages in threads even if they are not interested in them. Maybe there should be a way to whitelist/blacklist threads to exclude some from the /sync response?