# Rough draft for the intended server architecture Very messy, just here to get my thought down somewhere. Each thread is represented as its own 'file' (the exact format used to store messages is not really relevant, but file-based is easy to handle at least), and clients 'sync' this file to themselves. Whether a client wants to keep a copy of the file or always load a new version depends on the client itself and what type of thread it is. For example, public channels with huge amounts of messages make more sense to just sync the last 100 messages of at a time. An account always connects to a 'home server' of sorts, so user@server.com or whatever. The server takes care of connecting to other servers when need be. Each account additionally has an event queue, such as "you got invited to thread ABC by someone@somewhere" which always accepts new events. The client should request the event queue upon connecting (or should it be done automatically?) A client tells the home server which threads it's interested in at the moment via the SYNC command. If the SYNC command is to a thread on another server, a new connection is opened up (if one doesn't exist already), and the SYNC is forwarded. SYNC can take parameters for thread history, so SYNC 17\nSTART = 10\nEND = -20 skips the first ten bytes and the last twenty (off by one?). The number after SYNC specifies how many bytes are in the header, i.e. how many characters follow the first newline. Omitting the END parameter means that the client is interested in getting new messages as they come in, i.e. should be placed in a 'listening' state. The other server should send the home server an update whenever anyone adds anything to the thread. The home server is responsible for keeping track of which accounts are interested in which threads, the other server should only see 'this server is interested in this thread'. If no accounts are interested in a thread, the home server should send a command to signify this (CLOSE? STOP? DESYNC? Some other command name?) Messages are built of a header, consisting of some = parameters, and a body that's been encoded with a specific 'lark formatting', just replacing all = -characters with \= (or %=? Some other combination?). Clients must take care of encoding and decoding, servers are required to check that the body follows the ecoding but are not required to fix it for the user. (I did some benchmarks and checking is significantly faster than fixing) The server (/collection of server instances?) maintain a shared state, such that each connection (client <-> server and server <-> server) has its own queue. When a message is added to a thread, all connections interested in that thread should have the message added to their outgoing queue. The sender must also be interested in a thread. Each thread can have limitations on who is allowed to send to it (or do other operations), which I haven't really thought about yet, but they should presumably be checked at sendtime as well. Connection queues are presumably fairly simple, just add files to a directory and a reference to those files in some queue file that's locked by whoever is dealing with it. Server <-> server connections are presumably fairly easy as well, keep a map of threads on the other server that we're interested in and what account is interested in it, and then just directly add incoming messages to client connection queues. Messages should be delivered so that at least ones to the same thread are sent to clients in the order that they arrived, between threads they can arrive in different orders. Have to think about how errors are reported, give each command a UUID or just specify that client should wait for a response to a command before sending another one? I guess it depends on the command, SYNC contains enough metainformation to just say "right, this thread didn't like that" etc. Server <-> server it's pretty easy to keep track of which queue a message should be added to, but it's not entirely obvious how the list of which connections are listening to which thread should be handled. One option could be inotify of the thread file, but that requires separate handling of inotify/kqueue for Linux/BSD. Simplest option would arguably just be that each connection is given a turn to run often enough that a small delay is insignificant, and each connection queries the relevant local threads on their own, and send out any new bytes since the thread file was last read. One option I thought about was creating a named pipe for each thread, and on new messages, the sending connection handler writes something into it, and listeners poll() for the read end. Unsure of the semantics here, docs don't outright say something like it wouldn't work but I'm not sure which all polls() get notified. Also, one FD per thread, might be a lot for server <-> server connections?