Load messages on demand
If a group contains a lot of messages, it's expensive to load all the messages when the user views the group.
Some clients use metadata to avoid loading messages. Message bodies can then be loaded on demand as they become visible. But this is still expensive if there are lots of messages and/or lots of metadata per message.
Ideally we'd use something like the MessageTracker to store summary information, then load the messages and/or metadata on demand.
One of the tasks here is to determine what summary information each client needs. For example, the forum client needs to know the number of unread posts above and below the viewport. It may also need to know the sort position of the first unread post above and below the viewport so it can jump to those posts.
Sort order will be relevant to any client that loads messages on demand. If we want to load messages a page at a time, the database needs to know how to sort the messages. But sort order is client-dependent. For example, the blog client may want to sort posts by date, whereas the forum client sorts them by depth-first traversal order of the reply tree.
We can capture both of these orders (and hopefully others) by adding a label to each message. From the database's point of view, the label is just an opaque string of bytes. The database sorts the labels in lexicographic order, and messages and metadata can be retrieved by their positions in the sort order. The client is reponsible for labelling messages to achieve the desired sort order.
For the blog client, the label can just be a big-endian representation of the timestamp. For the forum client, the label can be the concatenated timestamps of the post's ancestors and the post itself. These labels will sort in the same order as depth-first traversal of the tree, visiting siblings in timestamp order.
123 +-123/234 +-123/345 234 +-234/345 +-234/345/456 345 567
(This doesn't rely on the rule that a post has a higher timestamp than its parent.)
This approach wouldn't be efficient for dynamic sort orders. For example, if the forum client wanted to sort siblings by the number of upvotes, we could calculate the labels as with timestamps, but adding an upvote to a post would require relabelling the post and all its descendents.