From a14bacc9c13309593c6eab2d19b70bcd315d193d Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 21 Feb 2020 19:36:16 +0100 Subject: [PATCH] Keep in cache the Id of the last seen post for backlogging purposes --- appservice/account.go | 14 ++++++++++++++ connector/connector.go | 7 +++++++ connector/mattermost/mattermost.go | 12 ++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/appservice/account.go b/appservice/account.go index e2f2ee9..e17c425 100644 --- a/appservice/account.go +++ b/appservice/account.go @@ -315,3 +315,17 @@ func (a *Account) eventInternal(event *Event) error { return nil } } + +// ---- + +func (a *Account) CacheGet(key string) string { + cache_key := fmt.Sprintf("%s/account/%s/%s/%s", + a.Protocol, a.MatrixUser, a.AccountName, key) + return dbCacheGet(cache_key) +} + +func (a *Account) CachePut(key string, value string) { + cache_key := fmt.Sprintf("%s/account/%s/%s/%s", + a.Protocol, a.MatrixUser, a.AccountName, key) + dbCachePut(cache_key, value) +} diff --git a/connector/connector.go b/connector/connector.go index 30dfea4..3a2e20c 100644 --- a/connector/connector.go +++ b/connector/connector.go @@ -84,6 +84,13 @@ type Handler interface { // Called when an event occurs in a room // This must not be called for events authored by the user of the connection Event(event *Event) + + // These two functions enable the connector to access a simple key/value + // database to cache some information in order not to generate useless events. + // The connector should function when they are not implemented, + // in which case CacheGet always returns "" + CachePut(key string, value string) + CacheGet(key string) string } type EventType int diff --git a/connector/mattermost/mattermost.go b/connector/mattermost/mattermost.go index 117286b..ab612ba 100644 --- a/connector/mattermost/mattermost.go +++ b/connector/mattermost/mattermost.go @@ -337,6 +337,7 @@ func (mm *Mattermost) handleConnected() { mm.handler.RoomInfoUpdated(id, UserID(""), room_info) // Update member list + // TODO (when this will be slow, i.e. hundreds of members): do only a diff members, resp := mm.conn.Client.GetChannelMembers(ch.Id, 0, 1000, "") if resp.Error == nil { for _, mem := range *members { @@ -356,8 +357,14 @@ func (mm *Mattermost) handleConnected() { } // Read backlog - // TODO: remember what was the last seen post in this channel - backlog, resp := mm.conn.Client.GetPostsForChannel(ch.Id, 0, 1000, "") + var backlog *model.PostList + last_seen_post := mm.handler.CacheGet(fmt.Sprintf("last_seen_%s", ch.Id)) + if last_seen_post != "" { + backlog, resp = mm.conn.Client.GetPostsAfter(ch.Id, last_seen_post, 0, 1000, "") + // TODO: if there are more than 1000, loop around + } else { + backlog, resp = mm.conn.Client.GetPostsForChannel(ch.Id, 0, 1000, "") + } if resp.Error == nil { for i := 0; i < len(backlog.Order); i++ { post_id := backlog.Order[len(backlog.Order)-i-1] @@ -519,6 +526,7 @@ func (mm *Mattermost) handlePost(channel_name string, post *model.Post, only_mes } else if post.Type == "" || post.Type == "me" { msg_ev.Room = roomId mm.handler.Event(msg_ev) + mm.handler.CachePut(fmt.Sprintf("last_seen_%s", post.ChannelId), post.Id) } else { return fmt.Errorf("Unhandled post type: %s", post.Type) }