mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-07-29 12:42:46 +00:00
Optimize history visibility checks (#2848)
This optimizes history visibility checks by (mostly) avoiding database hits. Possibly solves https://github.com/matrix-org/dendrite/issues/2777 Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
parent
0b21cb78aa
commit
2acc1d65fb
9 changed files with 181 additions and 36 deletions
|
@ -72,6 +72,7 @@ type Database interface {
|
|||
Events(ctx context.Context, eventNIDs []types.EventNID) ([]types.Event, error)
|
||||
// Look up snapshot NID for an event ID string
|
||||
SnapshotNIDFromEventID(ctx context.Context, eventID string) (types.StateSnapshotNID, error)
|
||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||
// Stores a matrix room event in the database. Returns the room NID, the state snapshot and the redacted event ID if any, or an error.
|
||||
StoreEvent(
|
||||
ctx context.Context, event *gomatrixserverlib.Event, authEventNIDs []types.EventNID,
|
||||
|
|
|
@ -22,11 +22,12 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
const eventsSchema = `
|
||||
|
@ -80,6 +81,9 @@ const insertEventSQL = "" +
|
|||
const selectEventSQL = "" +
|
||||
"SELECT event_nid, state_snapshot_nid FROM roomserver_events WHERE event_id = $1"
|
||||
|
||||
const bulkSelectSnapshotsForEventIDsSQL = "" +
|
||||
"SELECT event_id, state_snapshot_nid FROM roomserver_events WHERE event_id = ANY($1)"
|
||||
|
||||
// Bulk lookup of events by string ID.
|
||||
// Sort by the numeric IDs for event type and state key.
|
||||
// This means we can use binary search to lookup entries by type and state key.
|
||||
|
@ -150,6 +154,7 @@ const selectEventRejectedSQL = "" +
|
|||
type eventStatements struct {
|
||||
insertEventStmt *sql.Stmt
|
||||
selectEventStmt *sql.Stmt
|
||||
bulkSelectSnapshotsForEventIDsStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDExcludingRejectedStmt *sql.Stmt
|
||||
bulkSelectStateEventByNIDStmt *sql.Stmt
|
||||
|
@ -179,6 +184,7 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
|||
return s, sqlutil.StatementList{
|
||||
{&s.insertEventStmt, insertEventSQL},
|
||||
{&s.selectEventStmt, selectEventSQL},
|
||||
{&s.bulkSelectSnapshotsForEventIDsStmt, bulkSelectSnapshotsForEventIDsSQL},
|
||||
{&s.bulkSelectStateEventByIDStmt, bulkSelectStateEventByIDSQL},
|
||||
{&s.bulkSelectStateEventByIDExcludingRejectedStmt, bulkSelectStateEventByIDExcludingRejectedSQL},
|
||||
{&s.bulkSelectStateEventByNIDStmt, bulkSelectStateEventByNIDSQL},
|
||||
|
@ -230,6 +236,29 @@ func (s *eventStatements) SelectEvent(
|
|||
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
||||
}
|
||||
|
||||
func (s *eventStatements) BulkSelectSnapshotsFromEventIDs(
|
||||
ctx context.Context, txn *sql.Tx, eventIDs []string,
|
||||
) (map[types.StateSnapshotNID][]string, error) {
|
||||
stmt := sqlutil.TxStmt(txn, s.bulkSelectSnapshotsForEventIDsStmt)
|
||||
|
||||
rows, err := stmt.QueryContext(ctx, pq.Array(eventIDs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var eventID string
|
||||
var stateNID types.StateSnapshotNID
|
||||
result := make(map[types.StateSnapshotNID][]string)
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&eventID, &stateNID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[stateNID] = append(result[stateNID], eventID)
|
||||
}
|
||||
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// bulkSelectStateEventByID lookups a list of state events by event ID.
|
||||
// If not excluding rejected events, and any of the requested events are missing from
|
||||
// the database it returns a types.MissingEventError. If excluding rejected events,
|
||||
|
|
|
@ -5,8 +5,9 @@ import (
|
|||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
)
|
||||
|
||||
type RoomUpdater struct {
|
||||
|
@ -186,6 +187,10 @@ func (u *RoomUpdater) EventIDs(
|
|||
return u.d.EventsTable.BulkSelectEventID(ctx, u.txn, eventNIDs)
|
||||
}
|
||||
|
||||
func (u *RoomUpdater) BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error) {
|
||||
return u.d.EventsTable.BulkSelectSnapshotsFromEventIDs(ctx, u.txn, eventIDs)
|
||||
}
|
||||
|
||||
func (u *RoomUpdater) StateAtEventIDs(
|
||||
ctx context.Context, eventIDs []string,
|
||||
) ([]types.StateAtEvent, error) {
|
||||
|
|
|
@ -469,6 +469,23 @@ func (d *Database) events(
|
|||
eventNIDs = append(eventNIDs, nid)
|
||||
}
|
||||
}
|
||||
// If we don't need to get any events from the database, short circuit now
|
||||
if len(eventNIDs) == 0 {
|
||||
results := make([]types.Event, 0, len(inputEventNIDs))
|
||||
for _, nid := range inputEventNIDs {
|
||||
event, ok := events[nid]
|
||||
if !ok || event == nil {
|
||||
return nil, fmt.Errorf("event %d missing", nid)
|
||||
}
|
||||
results = append(results, types.Event{
|
||||
EventNID: nid,
|
||||
Event: event,
|
||||
})
|
||||
}
|
||||
if !redactionsArePermanent {
|
||||
d.applyRedactions(results)
|
||||
}
|
||||
}
|
||||
eventJSONs, err := d.EventJSONTable.BulkSelectEventJSON(ctx, txn, eventNIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -534,6 +551,12 @@ func (d *Database) events(
|
|||
return results, nil
|
||||
}
|
||||
|
||||
func (d *Database) BulkSelectSnapshotsFromEventIDs(
|
||||
ctx context.Context, eventIDs []string,
|
||||
) (map[types.StateSnapshotNID][]string, error) {
|
||||
return d.EventsTable.BulkSelectSnapshotsFromEventIDs(ctx, nil, eventIDs)
|
||||
}
|
||||
|
||||
func (d *Database) MembershipUpdater(
|
||||
ctx context.Context, roomID, targetUserID string,
|
||||
targetLocal bool, roomVersion gomatrixserverlib.RoomVersion,
|
||||
|
|
|
@ -23,11 +23,12 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal"
|
||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
const eventsSchema = `
|
||||
|
@ -57,6 +58,9 @@ const insertEventSQL = `
|
|||
const selectEventSQL = "" +
|
||||
"SELECT event_nid, state_snapshot_nid FROM roomserver_events WHERE event_id = $1"
|
||||
|
||||
const bulkSelectSnapshotsForEventIDsSQL = "" +
|
||||
"SELECT event_id, state_snapshot_nid FROM roomserver_events WHERE event_id IN ($1)"
|
||||
|
||||
// Bulk lookup of events by string ID.
|
||||
// Sort by the numeric IDs for event type and state key.
|
||||
// This means we can use binary search to lookup entries by type and state key.
|
||||
|
@ -124,6 +128,7 @@ type eventStatements struct {
|
|||
db *sql.DB
|
||||
insertEventStmt *sql.Stmt
|
||||
selectEventStmt *sql.Stmt
|
||||
bulkSelectSnapshotsForEventIDsStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDStmt *sql.Stmt
|
||||
bulkSelectStateEventByIDExcludingRejectedStmt *sql.Stmt
|
||||
bulkSelectStateAtEventByIDStmt *sql.Stmt
|
||||
|
@ -153,6 +158,7 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
|||
return s, sqlutil.StatementList{
|
||||
{&s.insertEventStmt, insertEventSQL},
|
||||
{&s.selectEventStmt, selectEventSQL},
|
||||
{&s.bulkSelectSnapshotsForEventIDsStmt, bulkSelectSnapshotsForEventIDsSQL},
|
||||
{&s.bulkSelectStateEventByIDStmt, bulkSelectStateEventByIDSQL},
|
||||
{&s.bulkSelectStateEventByIDExcludingRejectedStmt, bulkSelectStateEventByIDExcludingRejectedSQL},
|
||||
{&s.bulkSelectStateAtEventByIDStmt, bulkSelectStateAtEventByIDSQL},
|
||||
|
@ -203,6 +209,40 @@ func (s *eventStatements) SelectEvent(
|
|||
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
||||
}
|
||||
|
||||
func (s *eventStatements) BulkSelectSnapshotsFromEventIDs(
|
||||
ctx context.Context, txn *sql.Tx, eventIDs []string,
|
||||
) (map[types.StateSnapshotNID][]string, error) {
|
||||
qry := strings.Replace(bulkSelectSnapshotsForEventIDsSQL, "($1)", sqlutil.QueryVariadic(len(eventIDs)), 1)
|
||||
stmt, err := s.db.Prepare(qry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, stmt, "BulkSelectSnapshotsFromEventIDs: stmt.close() failed")
|
||||
|
||||
params := make([]interface{}, len(eventIDs))
|
||||
for i := range eventIDs {
|
||||
params[i] = eventIDs[i]
|
||||
}
|
||||
|
||||
rows, err := stmt.QueryContext(ctx, params...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogIfError(ctx, rows, "BulkSelectSnapshotsFromEventIDs: rows.close() failed")
|
||||
|
||||
var eventID string
|
||||
var stateNID types.StateSnapshotNID
|
||||
result := make(map[types.StateSnapshotNID][]string)
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&eventID, &stateNID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[stateNID] = append(result[stateNID], eventID)
|
||||
}
|
||||
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// bulkSelectStateEventByID lookups a list of state events by event ID.
|
||||
// If not excluding rejected events, and any of the requested events are missing from
|
||||
// the database it returns a types.MissingEventError. If excluding rejected events,
|
||||
|
|
|
@ -44,6 +44,7 @@ type Events interface {
|
|||
referenceSHA256 []byte, authEventNIDs []types.EventNID, depth int64, isRejected bool,
|
||||
) (types.EventNID, types.StateSnapshotNID, error)
|
||||
SelectEvent(ctx context.Context, txn *sql.Tx, eventID string) (types.EventNID, types.StateSnapshotNID, error)
|
||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, txn *sql.Tx, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||
// bulkSelectStateEventByID lookups a list of state events by event ID.
|
||||
// If any of the requested events are missing from the database it returns a types.MissingEventError
|
||||
BulkSelectStateEventByID(ctx context.Context, txn *sql.Tx, eventIDs []string, excludeRejected bool) ([]types.StateEntry, error)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue