Try to optimize database requests

This commit is contained in:
Till Faelligen 2022-07-22 12:27:36 +02:00
parent 53885048a8
commit e30565c029
No known key found for this signature in database
GPG key ID: 3DF82D8AB9211D4E
3 changed files with 47 additions and 31 deletions

View file

@ -197,10 +197,10 @@ func StateBeforeEvent(ctx context.Context, db storage.Database, info *types.Room
return roomState.LoadCombinedStateAfterEvents(ctx, prevState) return roomState.LoadCombinedStateAfterEvents(ctx, prevState)
} }
func MembershipAtEvent(ctx context.Context, db storage.Database, info *types.RoomInfo, eventID string, stateKeyNID types.EventStateKeyNID) ([]types.StateEntry, error) { func MembershipAtEvent(ctx context.Context, db storage.Database, info *types.RoomInfo, eventIDs []string, stateKeyNID types.EventStateKeyNID) (map[string][]types.StateEntry, error) {
roomState := state.NewStateResolution(db, info) roomState := state.NewStateResolution(db, info)
// Fetch the state as it was when this event was fired // Fetch the state as it was when this event was fired
return roomState.LoadMembershipAtEvent(ctx, eventID, stateKeyNID) return roomState.LoadMembershipAtEvent(ctx, eventIDs, stateKeyNID)
} }
func LoadEvents( func LoadEvents(

View file

@ -226,12 +226,14 @@ func (r *Queryer) QueryMembershipAtEvent(
return fmt.Errorf("requested stateKeyNID for %s was not found", request.UserID) return fmt.Errorf("requested stateKeyNID for %s was not found", request.UserID)
} }
stateEntries, err := helpers.MembershipAtEvent(ctx, r.DB, info, request.EventIDs, stateKeyNIDs[request.UserID])
if err != nil {
return fmt.Errorf("unable to get state before event: %w", err)
}
for _, eventID := range request.EventIDs { for _, eventID := range request.EventIDs {
stateEntries, err := helpers.MembershipAtEvent(ctx, r.DB, info, eventID, stateKeyNIDs[request.UserID]) stateEntry := stateEntries[eventID]
if err != nil { memberships, err := helpers.GetMembershipsAtState(ctx, r.DB, stateEntry, false)
return fmt.Errorf("unable to get state before event: %w", err)
}
memberships, err := helpers.GetMembershipsAtState(ctx, r.DB, stateEntries, false)
if err != nil { if err != nil {
return fmt.Errorf("unable to get memberships at state: %w", err) return fmt.Errorf("unable to get memberships at state: %w", err)
} }

View file

@ -124,43 +124,57 @@ func (v *StateResolution) LoadStateAtEvent(
} }
func (v *StateResolution) LoadMembershipAtEvent( func (v *StateResolution) LoadMembershipAtEvent(
ctx context.Context, eventID string, stateKeyNID types.EventStateKeyNID, ctx context.Context, eventIDs []string, stateKeyNID types.EventStateKeyNID,
) ([]types.StateEntry, error) { ) (map[string][]types.StateEntry, error) {
span, ctx := opentracing.StartSpanFromContext(ctx, "StateResolution.LoadMembershipAtEvent") span, ctx := opentracing.StartSpanFromContext(ctx, "StateResolution.LoadMembershipAtEvent")
defer span.Finish() defer span.Finish()
snapshotNID, err := v.db.SnapshotNIDFromEventID(ctx, eventID) // De-dupe snapshotNIDs
if err != nil { snapshotNIDMap := make(map[types.StateSnapshotNID][]string) // map from snapshot NID to eventIDs
return nil, fmt.Errorf("LoadStateAtEvent.SnapshotNIDFromEventID failed for event %s : %w", eventID, err) for i := range eventIDs {
} eventID := eventIDs[i]
if snapshotNID == 0 { snapshotNID, err := v.db.SnapshotNIDFromEventID(ctx, eventID)
return nil, fmt.Errorf("LoadStateAtEvent.SnapshotNIDFromEventID(%s) returned 0 NID, was this event stored?", eventID) if err != nil {
return nil, fmt.Errorf("LoadStateAtEvent.SnapshotNIDFromEventID failed for event %s : %w", eventID, err)
}
if snapshotNID == 0 {
return nil, fmt.Errorf("LoadStateAtEvent.SnapshotNIDFromEventID(%s) returned 0 NID, was this event stored?", eventID)
}
snapshotNIDMap[snapshotNID] = append(snapshotNIDMap[snapshotNID], eventID)
} }
stateBlockNIDLists, err := v.db.StateBlockNIDs(ctx, []types.StateSnapshotNID{snapshotNID}) snapshotNIDs := make([]types.StateSnapshotNID, 0, len(snapshotNIDMap))
if err != nil { for nid := range snapshotNIDMap {
return nil, err snapshotNIDs = append(snapshotNIDs, nid)
} }
// We've asked for exactly one snapshot from the db so we should have exactly one entry in the result.
stateBlockNIDList := stateBlockNIDLists[0]
// Query the membership event for the user at the given stateblocks stateBlockNIDLists, err := v.db.StateBlockNIDs(ctx, snapshotNIDs)
stateEntryLists, err := v.db.StateEntriesForTuples(ctx, stateBlockNIDList.StateBlockNIDs, []types.StateKeyTuple{
{
EventTypeNID: types.MRoomMemberNID,
EventStateKeyNID: stateKeyNID,
},
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result []types.StateEntry result := make(map[string][]types.StateEntry)
for _, x := range stateEntryLists { for _, stateBlockNIDList := range stateBlockNIDLists {
if len(x.StateEntries) > 0 { // Query the membership event for the user at the given stateblocks
result = append(result, x.StateEntries...) stateEntryLists, err := v.db.StateEntriesForTuples(ctx, stateBlockNIDList.StateBlockNIDs, []types.StateKeyTuple{
{
EventTypeNID: types.MRoomMemberNID,
EventStateKeyNID: stateKeyNID,
},
})
if err != nil {
return nil, err
}
evIDs := snapshotNIDMap[stateBlockNIDList.StateSnapshotNID]
for _, evID := range evIDs {
for _, x := range stateEntryLists {
result[evID] = append(result[evID], x.StateEntries...)
}
} }
} }
return result, nil return result, nil
} }