mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-17 03:43:11 -06:00
113 lines
4.1 KiB
Go
113 lines
4.1 KiB
Go
package query
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/matrix-org/dendrite/roomserver/storage"
|
|
"github.com/matrix-org/dendrite/roomserver/types"
|
|
"github.com/matrix-org/gomatrixserverlib"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// backfillRequester implements gomatrixserverlib.BackfillRequester
|
|
type backfillRequester struct {
|
|
db storage.Database
|
|
fedClient *gomatrixserverlib.FederationClient
|
|
thisServer gomatrixserverlib.ServerName
|
|
|
|
// per-request state
|
|
servers []gomatrixserverlib.ServerName
|
|
stateIDs []string
|
|
}
|
|
|
|
func (b *backfillRequester) StateIDsBeforeEvent(ctx context.Context, roomID, atEventID string) ([]string, error) {
|
|
c := gomatrixserverlib.FederatedStateProvider{
|
|
FedClient: b.fedClient,
|
|
AuthEventsOnly: true,
|
|
Server: b.servers[0],
|
|
}
|
|
res, err := c.StateIDsAtEvent(ctx, roomID, atEventID)
|
|
b.stateIDs = res
|
|
return res, err
|
|
}
|
|
|
|
func (b *backfillRequester) StateBeforeEvent(ctx context.Context, roomVer gomatrixserverlib.RoomVersion, roomID, atEventID string, eventIDs []string) (map[string]*gomatrixserverlib.Event, error) {
|
|
c := gomatrixserverlib.FederatedStateProvider{
|
|
FedClient: b.fedClient,
|
|
AuthEventsOnly: true,
|
|
Server: b.servers[0],
|
|
}
|
|
return c.StateAtEvent(ctx, roomVer, roomID, atEventID, eventIDs)
|
|
}
|
|
|
|
// ServersAtEvent is called when trying to determine which server to request from.
|
|
// It returns a list of servers which can be queried for backfill requests. These servers
|
|
// will be servers that are in the room already. The entries at the beginning are preferred servers
|
|
// and will be tried first. An empty list will fail the request.
|
|
func (b *backfillRequester) ServersAtEvent(ctx context.Context, roomID, eventID string) (servers []gomatrixserverlib.ServerName) {
|
|
// getMembershipsBeforeEventNID requires a NID, so retrieving the NID for
|
|
// the event is necessary.
|
|
NIDs, err := b.db.EventNIDs(ctx, []string{eventID})
|
|
if err != nil {
|
|
logrus.WithField("event_id", eventID).WithError(err).Error("ServersAtEvent: failed to get event NID for event")
|
|
return
|
|
}
|
|
|
|
// Retrieve all "m.room.member" state events of "join" membership, which
|
|
// contains the list of users in the room before the event, therefore all
|
|
// the servers in it at that moment.
|
|
events, err := getMembershipsBeforeEventNID(ctx, b.db, NIDs[eventID], true)
|
|
if err != nil {
|
|
logrus.WithField("event_id", eventID).WithError(err).Error("ServersAtEvent: failed to get memberships before event")
|
|
return
|
|
}
|
|
|
|
// Store the server names in a temporary map to avoid duplicates.
|
|
serverSet := make(map[gomatrixserverlib.ServerName]bool)
|
|
for _, event := range events {
|
|
serverSet[event.Origin()] = true
|
|
}
|
|
for server := range serverSet {
|
|
if server == b.thisServer {
|
|
continue
|
|
}
|
|
servers = append(servers, server)
|
|
}
|
|
b.servers = servers
|
|
return
|
|
}
|
|
|
|
// Backfill performs a backfill request to the given server.
|
|
// https://matrix.org/docs/spec/server_server/latest#get-matrix-federation-v1-backfill-roomid
|
|
func (b *backfillRequester) Backfill(ctx context.Context, server gomatrixserverlib.ServerName, roomID string, fromEventIDs []string, limit int) (*gomatrixserverlib.Transaction, error) {
|
|
tx, err := b.fedClient.Backfill(ctx, server, roomID, limit, fromEventIDs)
|
|
return &tx, err
|
|
}
|
|
|
|
func (b *backfillRequester) ProvideEvents(roomVer gomatrixserverlib.RoomVersion, eventIDs []string) ([]gomatrixserverlib.Event, error) {
|
|
logrus.Info("backfillRequester.ProvideEvents ", eventIDs)
|
|
ctx := context.Background()
|
|
nidMap, err := b.db.EventNIDs(ctx, eventIDs)
|
|
if err != nil {
|
|
logrus.WithError(err).WithField("event_ids", eventIDs).Error("Failed to find events")
|
|
return nil, err
|
|
}
|
|
eventNIDs := make([]types.EventNID, len(nidMap))
|
|
i := 0
|
|
for _, nid := range nidMap {
|
|
eventNIDs[i] = nid
|
|
i++
|
|
}
|
|
eventsWithNids, err := b.db.Events(ctx, eventNIDs)
|
|
if err != nil {
|
|
logrus.WithError(err).WithField("event_nids", eventNIDs).Error("Failed to load events")
|
|
return nil, err
|
|
}
|
|
events := make([]gomatrixserverlib.Event, len(eventsWithNids))
|
|
for i := range eventsWithNids {
|
|
events[i] = eventsWithNids[i].Event
|
|
}
|
|
logrus.Infof("backfillRequester.ProvideEvents Returning %+v", events)
|
|
return events, nil
|
|
}
|