aboutsummaryrefslogtreecommitdiff
path: root/syncapi/sync/requestpool.go
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2020-11-20 11:29:02 +0000
committerGitHub <noreply@github.com>2020-11-20 11:29:02 +0000
commitc636be5070b575a2b4e986e1fd7fc0ba24991907 (patch)
tree9fb1d986afe8f8e89091a270760de2dc9b4777ae /syncapi/sync/requestpool.go
parent13cbd50dc26721792a36ab47c17e62b7bb965a85 (diff)
Update last seen on sync requests (#1593)
* Update last seen on sync requests * Fix MSC2836 unit tests * Only update once per minute * Remove debug logging * Configurable option * Simplify updateLastSeen/cleanLastSeen
Diffstat (limited to 'syncapi/sync/requestpool.go')
-rw-r--r--syncapi/sync/requestpool.go54
1 files changed, 52 insertions, 2 deletions
diff --git a/syncapi/sync/requestpool.go b/syncapi/sync/requestpool.go
index 8a79737a..61f8c46f 100644
--- a/syncapi/sync/requestpool.go
+++ b/syncapi/sync/requestpool.go
@@ -19,10 +19,14 @@ package sync
import (
"context"
"fmt"
+ "net"
"net/http"
+ "strings"
+ "sync"
"time"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
+ "github.com/matrix-org/dendrite/internal/config"
keyapi "github.com/matrix-org/dendrite/keyserver/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/syncapi/internal"
@@ -37,18 +41,62 @@ import (
// RequestPool manages HTTP long-poll connections for /sync
type RequestPool struct {
db storage.Database
+ cfg *config.SyncAPI
userAPI userapi.UserInternalAPI
notifier *Notifier
keyAPI keyapi.KeyInternalAPI
rsAPI roomserverAPI.RoomserverInternalAPI
+ lastseen sync.Map
}
// NewRequestPool makes a new RequestPool
func NewRequestPool(
- db storage.Database, n *Notifier, userAPI userapi.UserInternalAPI, keyAPI keyapi.KeyInternalAPI,
+ db storage.Database, cfg *config.SyncAPI, n *Notifier,
+ userAPI userapi.UserInternalAPI, keyAPI keyapi.KeyInternalAPI,
rsAPI roomserverAPI.RoomserverInternalAPI,
) *RequestPool {
- return &RequestPool{db, userAPI, n, keyAPI, rsAPI}
+ rp := &RequestPool{db, cfg, userAPI, n, keyAPI, rsAPI, sync.Map{}}
+ go rp.cleanLastSeen()
+ return rp
+}
+
+func (rp *RequestPool) cleanLastSeen() {
+ for {
+ rp.lastseen.Range(func(key interface{}, _ interface{}) bool {
+ rp.lastseen.Delete(key)
+ return true
+ })
+ time.Sleep(time.Minute)
+ }
+}
+
+func (rp *RequestPool) updateLastSeen(req *http.Request, device *userapi.Device) {
+ if _, ok := rp.lastseen.LoadOrStore(device.UserID+device.ID, struct{}{}); ok {
+ return
+ }
+
+ remoteAddr := req.RemoteAddr
+ if rp.cfg.RealIPHeader != "" {
+ if header := req.Header.Get(rp.cfg.RealIPHeader); header != "" {
+ // TODO: Maybe this isn't great but it will satisfy both X-Real-IP
+ // and X-Forwarded-For (which can be a list where the real client
+ // address is the first listed address). Make more intelligent?
+ addresses := strings.Split(header, ",")
+ if ip := net.ParseIP(addresses[0]); ip != nil {
+ remoteAddr = addresses[0]
+ }
+ }
+ }
+
+ lsreq := &userapi.PerformLastSeenUpdateRequest{
+ UserID: device.UserID,
+ DeviceID: device.ID,
+ RemoteAddr: remoteAddr,
+ }
+ lsres := &userapi.PerformLastSeenUpdateResponse{}
+ go rp.userAPI.PerformLastSeenUpdate(req.Context(), lsreq, lsres) // nolint:errcheck
+
+ rp.lastseen.Store(device.UserID+device.ID, time.Now())
}
// OnIncomingSyncRequest is called when a client makes a /sync request. This function MUST be
@@ -74,6 +122,8 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *userapi.
"limit": syncReq.limit,
})
+ rp.updateLastSeen(req, device)
+
currPos := rp.notifier.CurrentPosition()
if rp.shouldReturnImmediately(syncReq) {