mirror of
https://github.com/matrix-org/dendrite.git
synced 2024-11-29 17:51:56 -06:00
Limit presence in /sync
responses (#2394)
* Use filter and limit presence count * More limiting * More limiting * Fix unit test * Also limit presence by last_active_ts * Update query, use "from" as the initial lastPos * Get 1000 presence events, they are filtered later Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
parent
8683ff78b1
commit
21ee5b36a4
|
@ -159,6 +159,6 @@ type Database interface {
|
||||||
type Presence interface {
|
type Presence interface {
|
||||||
UpdatePresence(ctx context.Context, userID string, presence types.Presence, statusMsg *string, lastActiveTS gomatrixserverlib.Timestamp, fromSync bool) (types.StreamPosition, error)
|
UpdatePresence(ctx context.Context, userID string, presence types.Presence, statusMsg *string, lastActiveTS gomatrixserverlib.Timestamp, fromSync bool) (types.StreamPosition, error)
|
||||||
GetPresence(ctx context.Context, userID string) (*types.PresenceInternal, error)
|
GetPresence(ctx context.Context, userID string) (*types.PresenceInternal, error)
|
||||||
PresenceAfter(ctx context.Context, after types.StreamPosition) (map[string]*types.PresenceInternal, error)
|
PresenceAfter(ctx context.Context, after types.StreamPosition, filter gomatrixserverlib.EventFilter) (map[string]*types.PresenceInternal, error)
|
||||||
MaxStreamPositionForPresence(ctx context.Context) (types.StreamPosition, error)
|
MaxStreamPositionForPresence(ctx context.Context) (types.StreamPosition, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package postgres
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
@ -72,7 +73,8 @@ const selectMaxPresenceSQL = "" +
|
||||||
const selectPresenceAfter = "" +
|
const selectPresenceAfter = "" +
|
||||||
" SELECT id, user_id, presence, status_msg, last_active_ts" +
|
" SELECT id, user_id, presence, status_msg, last_active_ts" +
|
||||||
" FROM syncapi_presence" +
|
" FROM syncapi_presence" +
|
||||||
" WHERE id > $1"
|
" WHERE id > $1 AND last_active_ts >= $2" +
|
||||||
|
" ORDER BY id ASC LIMIT $3"
|
||||||
|
|
||||||
type presenceStatements struct {
|
type presenceStatements struct {
|
||||||
upsertPresenceStmt *sql.Stmt
|
upsertPresenceStmt *sql.Stmt
|
||||||
|
@ -144,11 +146,12 @@ func (p *presenceStatements) GetMaxPresenceID(ctx context.Context, txn *sql.Tx)
|
||||||
func (p *presenceStatements) GetPresenceAfter(
|
func (p *presenceStatements) GetPresenceAfter(
|
||||||
ctx context.Context, txn *sql.Tx,
|
ctx context.Context, txn *sql.Tx,
|
||||||
after types.StreamPosition,
|
after types.StreamPosition,
|
||||||
|
filter gomatrixserverlib.EventFilter,
|
||||||
) (presences map[string]*types.PresenceInternal, err error) {
|
) (presences map[string]*types.PresenceInternal, err error) {
|
||||||
presences = make(map[string]*types.PresenceInternal)
|
presences = make(map[string]*types.PresenceInternal)
|
||||||
stmt := sqlutil.TxStmt(txn, p.selectPresenceAfterStmt)
|
stmt := sqlutil.TxStmt(txn, p.selectPresenceAfterStmt)
|
||||||
|
afterTS := gomatrixserverlib.AsTimestamp(time.Now().Add(time.Minute * -5))
|
||||||
rows, err := stmt.QueryContext(ctx, after)
|
rows, err := stmt.QueryContext(ctx, after, afterTS, filter.Limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1056,8 +1056,8 @@ func (s *Database) GetPresence(ctx context.Context, userID string) (*types.Prese
|
||||||
return s.Presence.GetPresenceForUser(ctx, nil, userID)
|
return s.Presence.GetPresenceForUser(ctx, nil, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Database) PresenceAfter(ctx context.Context, after types.StreamPosition) (map[string]*types.PresenceInternal, error) {
|
func (s *Database) PresenceAfter(ctx context.Context, after types.StreamPosition, filter gomatrixserverlib.EventFilter) (map[string]*types.PresenceInternal, error) {
|
||||||
return s.Presence.GetPresenceAfter(ctx, nil, after)
|
return s.Presence.GetPresenceAfter(ctx, nil, after, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Database) MaxStreamPositionForPresence(ctx context.Context) (types.StreamPosition, error) {
|
func (s *Database) MaxStreamPositionForPresence(ctx context.Context) (types.StreamPosition, error) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ package sqlite3
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
@ -71,7 +72,8 @@ const selectMaxPresenceSQL = "" +
|
||||||
const selectPresenceAfter = "" +
|
const selectPresenceAfter = "" +
|
||||||
" SELECT id, user_id, presence, status_msg, last_active_ts" +
|
" SELECT id, user_id, presence, status_msg, last_active_ts" +
|
||||||
" FROM syncapi_presence" +
|
" FROM syncapi_presence" +
|
||||||
" WHERE id > $1"
|
" WHERE id > $1 AND last_active_ts >= $2" +
|
||||||
|
" ORDER BY id ASC LIMIT $3"
|
||||||
|
|
||||||
type presenceStatements struct {
|
type presenceStatements struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
|
@ -158,12 +160,12 @@ func (p *presenceStatements) GetMaxPresenceID(ctx context.Context, txn *sql.Tx)
|
||||||
// GetPresenceAfter returns the changes presences after a given stream id
|
// GetPresenceAfter returns the changes presences after a given stream id
|
||||||
func (p *presenceStatements) GetPresenceAfter(
|
func (p *presenceStatements) GetPresenceAfter(
|
||||||
ctx context.Context, txn *sql.Tx,
|
ctx context.Context, txn *sql.Tx,
|
||||||
after types.StreamPosition,
|
after types.StreamPosition, filter gomatrixserverlib.EventFilter,
|
||||||
) (presences map[string]*types.PresenceInternal, err error) {
|
) (presences map[string]*types.PresenceInternal, err error) {
|
||||||
presences = make(map[string]*types.PresenceInternal)
|
presences = make(map[string]*types.PresenceInternal)
|
||||||
stmt := sqlutil.TxStmt(txn, p.selectPresenceAfterStmt)
|
stmt := sqlutil.TxStmt(txn, p.selectPresenceAfterStmt)
|
||||||
|
afterTS := gomatrixserverlib.AsTimestamp(time.Now().Add(time.Minute * -5))
|
||||||
rows, err := stmt.QueryContext(ctx, after)
|
rows, err := stmt.QueryContext(ctx, after, afterTS, filter.Limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,5 +188,5 @@ type Presence interface {
|
||||||
UpsertPresence(ctx context.Context, txn *sql.Tx, userID string, statusMsg *string, presence types.Presence, lastActiveTS gomatrixserverlib.Timestamp, fromSync bool) (pos types.StreamPosition, err error)
|
UpsertPresence(ctx context.Context, txn *sql.Tx, userID string, statusMsg *string, presence types.Presence, lastActiveTS gomatrixserverlib.Timestamp, fromSync bool) (pos types.StreamPosition, err error)
|
||||||
GetPresenceForUser(ctx context.Context, txn *sql.Tx, userID string) (presence *types.PresenceInternal, err error)
|
GetPresenceForUser(ctx context.Context, txn *sql.Tx, userID string) (presence *types.PresenceInternal, err error)
|
||||||
GetMaxPresenceID(ctx context.Context, txn *sql.Tx) (pos types.StreamPosition, err error)
|
GetMaxPresenceID(ctx context.Context, txn *sql.Tx) (pos types.StreamPosition, err error)
|
||||||
GetPresenceAfter(ctx context.Context, txn *sql.Tx, after types.StreamPosition) (presences map[string]*types.PresenceInternal, err error)
|
GetPresenceAfter(ctx context.Context, txn *sql.Tx, after types.StreamPosition, filter gomatrixserverlib.EventFilter) (presences map[string]*types.PresenceInternal, err error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ func (p *PresenceStreamProvider) IncrementalSync(
|
||||||
req *types.SyncRequest,
|
req *types.SyncRequest,
|
||||||
from, to types.StreamPosition,
|
from, to types.StreamPosition,
|
||||||
) types.StreamPosition {
|
) types.StreamPosition {
|
||||||
presences, err := p.DB.PresenceAfter(ctx, from)
|
// We pull out a larger number than the filter asks for, since we're filtering out events later
|
||||||
|
presences, err := p.DB.PresenceAfter(ctx, from, gomatrixserverlib.EventFilter{Limit: 1000})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.Log.WithError(err).Error("p.DB.PresenceAfter failed")
|
req.Log.WithError(err).Error("p.DB.PresenceAfter failed")
|
||||||
return from
|
return from
|
||||||
|
@ -72,6 +73,7 @@ func (p *PresenceStreamProvider) IncrementalSync(
|
||||||
req.Log.WithError(err).Error("unable to refresh notifier lists")
|
req.Log.WithError(err).Error("unable to refresh notifier lists")
|
||||||
return from
|
return from
|
||||||
}
|
}
|
||||||
|
NewlyJoinedLoop:
|
||||||
for _, roomID := range newlyJoined {
|
for _, roomID := range newlyJoined {
|
||||||
roomUsers := p.notifier.JoinedUsers(roomID)
|
roomUsers := p.notifier.JoinedUsers(roomID)
|
||||||
for i := range roomUsers {
|
for i := range roomUsers {
|
||||||
|
@ -86,11 +88,14 @@ func (p *PresenceStreamProvider) IncrementalSync(
|
||||||
req.Log.WithError(err).Error("unable to query presence for user")
|
req.Log.WithError(err).Error("unable to query presence for user")
|
||||||
return from
|
return from
|
||||||
}
|
}
|
||||||
|
if len(presences) > req.Filter.Presence.Limit {
|
||||||
|
break NewlyJoinedLoop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPos := to
|
lastPos := from
|
||||||
for _, presence := range presences {
|
for _, presence := range presences {
|
||||||
if presence == nil {
|
if presence == nil {
|
||||||
continue
|
continue
|
||||||
|
@ -135,6 +140,9 @@ func (p *PresenceStreamProvider) IncrementalSync(
|
||||||
if presence.StreamPos > lastPos {
|
if presence.StreamPos > lastPos {
|
||||||
lastPos = presence.StreamPos
|
lastPos = presence.StreamPos
|
||||||
}
|
}
|
||||||
|
if len(req.Response.Presence.Events) == req.Filter.Presence.Limit {
|
||||||
|
break
|
||||||
|
}
|
||||||
p.cache.Store(cacheKey, presence)
|
p.cache.Store(cacheKey, presence)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func (d dummyDB) GetPresence(ctx context.Context, userID string) (*types.Presenc
|
||||||
return &types.PresenceInternal{}, nil
|
return &types.PresenceInternal{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d dummyDB) PresenceAfter(ctx context.Context, after types.StreamPosition) (map[string]*types.PresenceInternal, error) {
|
func (d dummyDB) PresenceAfter(ctx context.Context, after types.StreamPosition, filter gomatrixserverlib.EventFilter) (map[string]*types.PresenceInternal, error) {
|
||||||
return map[string]*types.PresenceInternal{}, nil
|
return map[string]*types.PresenceInternal{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue