108 lines
4.4 KiB
Go
Raw Normal View History

2021-10-05 16:22:02 +01:00
package sync3
import (
"encoding/json"
"github.com/matrix-org/sliding-sync/internal"
"github.com/matrix-org/sliding-sync/sync3/caches"
)
type Room struct {
Name string `json:"name,omitempty"`
2023-07-18 10:42:13 +01:00
AvatarChange AvatarChange `json:"avatar,omitempty"`
2023-09-15 15:08:07 +02:00
Heroes []internal.Hero `json:"heroes,omitempty"`
RequiredState []json.RawMessage `json:"required_state,omitempty"`
Timeline []json.RawMessage `json:"timeline,omitempty"`
InviteState []json.RawMessage `json:"invite_state,omitempty"`
NotificationCount int64 `json:"notification_count"`
HighlightCount int64 `json:"highlight_count"`
Initial bool `json:"initial,omitempty"`
IsDM bool `json:"is_dm,omitempty"`
JoinedCount int `json:"joined_count,omitempty"`
InvitedCount *int `json:"invited_count,omitempty"`
PrevBatch string `json:"prev_batch,omitempty"`
add extensions for typing and receipts; bugfixes and additional perf improvements Features: - Add `typing` extension. - Add `receipts` extension. - Add comprehensive prometheus `/metrics` activated via `SYNCV3_PROM`. - Add `SYNCV3_PPROF` support. - Add `by_notification_level` sort order. - Add `include_old_rooms` support. - Add support for `$ME` and `$LAZY`. - Add correct filtering when `*,*` is used as `required_state`. - Add `num_live` to each room response to indicate how many timeline entries are live. Bug fixes: - Use a stricter comparison function on ranges: fixes an issue whereby UTs fail on go1.19 due to change in sorting algorithm. - Send back an `errcode` on HTTP errors (e.g expired sessions). - Remove `unsigned.txn_id` on insertion into the DB. Otherwise other users would see other users txn IDs :( - Improve range delta algorithm: previously it didn't handle cases like `[0,20] -> [20,30]` and would panic. - Send HTTP 400 for invalid range requests. - Don't publish no-op unread counts which just adds extra noise. - Fix leaking DB connections which could eventually consume all available connections. - Ensure we always unblock WaitUntilInitialSync even on invalid access tokens. Other code relies on WaitUntilInitialSync() actually returning at _some_ point e.g on startup we have N workers which bound the number of concurrent pollers made at any one time, we need to not just hog a worker forever. Improvements: - Greatly improve startup times of sync3 handlers by improving `JoinedRoomsTracker`: a modest amount of data would take ~28s to create the handler, now it takes 4s. - Massively improve initial initial v3 sync times, by refactoring `JoinedRoomsTracker`, from ~47s to <1s. - Add `SlidingSyncUntil...` in tests to reduce races. - Tweak the API shape of JoinedUsersForRoom to reduce state block processing time for large rooms from 63s to 39s. - Add trace task for initial syncs. - Include the proxy version in UA strings. - HTTP errors now wait 1s before returning to stop clients tight-looping on error. - Pending event buffer is now 2000. - Index the room ID first to cull the most events when returning timeline entries. Speeds up `SelectLatestEventsBetween` by a factor of 8. - Remove cancelled `m.room_key_requests` from the to-device inbox. Cuts down the amount of events in the inbox by ~94% for very large (20k+) inboxes, ~50% for moderate sized (200 events) inboxes. Adds book-keeping to remember the unacked to-device position for each client.
2022-12-14 18:53:55 +00:00
NumLive int `json:"num_live,omitempty"`
2023-08-11 14:49:45 +02:00
Timestamp uint64 `json:"timestamp,omitempty"`
}
// RoomConnMetadata represents a room as seen by one specific connection (hence one
// specific device).
type RoomConnMetadata struct {
// We enclose copies of the data kept in the global and user caches. These snapshots
// represent the state we reported to the connection the last time they requested
// a sync. Note that we are free to tweak fields within these copies if we want, to
// report more appropriate data to clients that kept in the caches.
internal.RoomMetadata
caches.UserRoomData
2023-05-23 16:14:06 +01:00
// plus any per-conn data.
// LastInterestedEventTimestamps is a map from list name to the origin_server_ts of
// the most recent event seen in the room since the user's join that the list is
// interested in.
//
2023-05-24 15:16:47 +01:00
// Connections can specify that a list is only interested in certain event types by
// providing "bump_event_types" in their sliding sync request. This happens on a
// list-by-list basis. Because the same room can appear in different lists with
// different bump criteria, we need to track a LastInterestedEventTimestamp for each
// list.
//
// While this conceptually tracks the internal.RoomMetadata.LastMessageTimestamp
// field, said field can decrease rapidly at any moment---so
// LastInterestedEventTimestamp can also decrease at any moment. When sorting by
// recency, this means rooms can suddenly fall down and jump back up the room
// list. See also the description of this in the React SDK docs:
// https://github.com/matrix-org/matrix-react-sdk/blob/526645c79160ab1ad4b4c3845de27d51263a405e/docs/room-list-store.md#tag-sorting-algorithm-recent
2023-05-24 15:16:47 +01:00
LastInterestedEventTimestamps map[string]uint64
}
2023-05-24 18:41:13 +01:00
// SameRoomAvatar checks if the fields relevant for room avatars have changed between the two metadatas.
// Returns true if there are no changes.
func (r *RoomConnMetadata) SameRoomAvatar(next *RoomConnMetadata) bool {
sameRoomAvatar := r.AvatarEvent == next.AvatarEvent
if next.IsDM {
// the avatar is the same IF:
// - the m.room.avatar event is the same AND
// - the heroes haven't changed AND
// - the number of heroes is 1
return sameRoomAvatar && sameHeroAvatars(r.Heroes, next.Heroes) && len(next.Heroes) == 1
}
// the avatar is the same IF:
// - the m.room.avatar event is the same
return sameRoomAvatar
}
func sameHeroAvatars(a, b []internal.Hero) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i].ID != b[i].ID {
return false
}
if a[i].Avatar != b[i].Avatar {
return false
}
}
return true
}
2023-05-24 18:41:13 +01:00
func (r *RoomConnMetadata) GetLastInterestedEventTimestamp(listKey string) uint64 {
ts, ok := r.LastInterestedEventTimestamps[listKey]
if ok {
return ts
2023-05-24 18:41:13 +01:00
}
// SetRoom is responsible for maintaining LastInterestedEventTimestamps.
// However, if a brand-new list appears we don't call SetRoom until we have
// some RoomEventUpdates to process. We need to ensure we hand back a sensible
// timestamp. So: use the (current) LastMessageTimestamp as a fallback.
// TODO: if we had access to the request's bump event types, we could lookup the
// a timestamp by event type from the global metadata (c.f. ConnState.load).
ts = r.LastMessageTimestamp
// Write this value into the map. If we don't and only uninteresting events
// arrive after, the fallback value will have jumped ahead despite nothing of
// interest happening.
r.LastInterestedEventTimestamps[listKey] = ts
2023-05-24 18:41:13 +01:00
return ts
}