Remove roominfo cache (#2615)

* Remove roominfo cache

It's the source of a number of race conditions which are seemingly causing bugs and CI failures.

* Make the linter less sad
This commit is contained in:
Neil Alexander 2022-08-03 17:14:21 +01:00 committed by GitHub
parent bbff41b44b
commit 2250768be1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 9 additions and 68 deletions

View File

@ -1,33 +0,0 @@
package caching
import (
"github.com/matrix-org/dendrite/roomserver/types"
)
// WARNING: This cache is mutable because it's entirely possible that
// the IsStub or StateSnaphotNID fields can change, even though the
// room version and room NID fields will not. This is only safe because
// the RoomInfoCache is used ONLY within the roomserver and because it
// will be kept up-to-date by the latest events updater. It MUST NOT be
// used from other components as we currently have no way to invalidate
// the cache in downstream components.
// RoomInfosCache contains the subset of functions needed for
// a room Info cache. It must only be used from the roomserver only
// It is not safe for use from other components.
type RoomInfoCache interface {
GetRoomInfo(roomID string) (roomInfo *types.RoomInfo, ok bool)
StoreRoomInfo(roomID string, roomInfo *types.RoomInfo)
}
// GetRoomInfo must only be called from the roomserver only. It is not
// safe for use from other components.
func (c Caches) GetRoomInfo(roomID string) (*types.RoomInfo, bool) {
return c.RoomInfos.Get(roomID)
}
// StoreRoomInfo must only be called from the roomserver only. It is not
// safe for use from other components.
func (c Caches) StoreRoomInfo(roomID string, roomInfo *types.RoomInfo) {
c.RoomInfos.Set(roomID, roomInfo)
}

View File

@ -7,7 +7,6 @@ import (
type RoomServerCaches interface { type RoomServerCaches interface {
RoomServerNIDsCache RoomServerNIDsCache
RoomVersionCache RoomVersionCache
RoomInfoCache
RoomServerEventsCache RoomServerEventsCache
EventStateKeyCache EventStateKeyCache
} }

View File

@ -29,7 +29,6 @@ type Caches struct {
RoomServerRoomIDs Cache[types.RoomNID, string] // room NID -> room ID RoomServerRoomIDs Cache[types.RoomNID, string] // room NID -> room ID
RoomServerEvents Cache[int64, *gomatrixserverlib.Event] // event NID -> event RoomServerEvents Cache[int64, *gomatrixserverlib.Event] // event NID -> event
RoomServerStateKeys Cache[types.EventStateKeyNID, string] // event NID -> event state key RoomServerStateKeys Cache[types.EventStateKeyNID, string] // event NID -> event state key
RoomInfos Cache[string, *types.RoomInfo] // room ID -> room info
FederationPDUs Cache[int64, *gomatrixserverlib.HeaderedEvent] // queue NID -> PDU FederationPDUs Cache[int64, *gomatrixserverlib.HeaderedEvent] // queue NID -> PDU
FederationEDUs Cache[int64, *gomatrixserverlib.EDU] // queue NID -> EDU FederationEDUs Cache[int64, *gomatrixserverlib.EDU] // queue NID -> EDU
SpaceSummaryRooms Cache[string, gomatrixserverlib.MSC2946SpacesResponse] // room ID -> space response SpaceSummaryRooms Cache[string, gomatrixserverlib.MSC2946SpacesResponse] // room ID -> space response

View File

@ -35,7 +35,6 @@ const (
roomNIDsCache roomNIDsCache
roomIDsCache roomIDsCache
roomEventsCache roomEventsCache
roomInfosCache
federationPDUsCache federationPDUsCache
federationEDUsCache federationEDUsCache
spaceSummaryRoomsCache spaceSummaryRoomsCache
@ -106,12 +105,6 @@ func NewRistrettoCache(maxCost config.DataUnit, maxAge time.Duration, enableProm
Prefix: eventStateKeyCache, Prefix: eventStateKeyCache,
MaxAge: maxAge, MaxAge: maxAge,
}, },
RoomInfos: &RistrettoCachePartition[string, *types.RoomInfo]{ // room ID -> room info
cache: cache,
Prefix: roomInfosCache,
Mutable: true,
MaxAge: maxAge,
},
FederationPDUs: &RistrettoCostedCachePartition[int64, *gomatrixserverlib.HeaderedEvent]{ // queue NID -> PDU FederationPDUs: &RistrettoCostedCachePartition[int64, *gomatrixserverlib.HeaderedEvent]{ // queue NID -> PDU
&RistrettoCachePartition[int64, *gomatrixserverlib.HeaderedEvent]{ &RistrettoCachePartition[int64, *gomatrixserverlib.HeaderedEvent]{
cache: cache, cache: cache,

View File

@ -156,30 +156,15 @@ func (d *Database) RoomInfo(ctx context.Context, roomID string) (*types.RoomInfo
} }
func (d *Database) roomInfo(ctx context.Context, txn *sql.Tx, roomID string) (*types.RoomInfo, error) { func (d *Database) roomInfo(ctx context.Context, txn *sql.Tx, roomID string) (*types.RoomInfo, error) {
roomInfo, ok := d.Cache.GetRoomInfo(roomID) roomInfo, err := d.RoomsTable.SelectRoomInfo(ctx, txn, roomID)
if ok && roomInfo != nil && !roomInfo.IsStub() {
// The data that's in the cache is not stubby, so return it.
return roomInfo, nil
}
// At this point we either don't have an entry in the cache, or
// it is stubby, so let's check the roomserver_rooms table again.
roomInfoFromDB, err := d.RoomsTable.SelectRoomInfo(ctx, txn, roomID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// If we have a stubby cache entry already, update it and return
// the reference to the cache entry.
if roomInfo != nil { if roomInfo != nil {
roomInfo.CopyFrom(roomInfoFromDB) d.Cache.StoreRoomServerRoomID(roomInfo.RoomNID, roomID)
return roomInfo, nil d.Cache.StoreRoomVersion(roomID, roomInfo.RoomVersion)
} }
// Otherwise, try to admit the data into the cache and return the return roomInfo, err
// new reference from the database.
if roomInfoFromDB != nil {
d.Cache.StoreRoomServerRoomID(roomInfoFromDB.RoomNID, roomID)
d.Cache.StoreRoomInfo(roomID, roomInfoFromDB)
}
return roomInfoFromDB, err
} }
func (d *Database) AddState( func (d *Database) AddState(
@ -504,8 +489,8 @@ func (d *Database) events(
fetchNIDList := make([]types.RoomNID, 0, len(uniqueRoomNIDs)) fetchNIDList := make([]types.RoomNID, 0, len(uniqueRoomNIDs))
for n := range uniqueRoomNIDs { for n := range uniqueRoomNIDs {
if roomID, ok := d.Cache.GetRoomServerRoomID(n); ok { if roomID, ok := d.Cache.GetRoomServerRoomID(n); ok {
if roomInfo, ok := d.Cache.GetRoomInfo(roomID); ok { if roomVersion, ok := d.Cache.GetRoomVersion(roomID); ok {
roomVersions[n] = roomInfo.RoomVersion roomVersions[n] = roomVersion
continue continue
} }
} }
@ -762,9 +747,6 @@ func (d *Database) MissingAuthPrevEvents(
func (d *Database) assignRoomNID( func (d *Database) assignRoomNID(
ctx context.Context, roomID string, roomVersion gomatrixserverlib.RoomVersion, ctx context.Context, roomID string, roomVersion gomatrixserverlib.RoomVersion,
) (types.RoomNID, error) { ) (types.RoomNID, error) {
if roomInfo, ok := d.Cache.GetRoomInfo(roomID); ok {
return roomInfo.RoomNID, nil
}
// Check if we already have a numeric ID in the database. // Check if we already have a numeric ID in the database.
roomNID, err := d.RoomsTable.SelectRoomNID(ctx, nil, roomID) roomNID, err := d.RoomsTable.SelectRoomNID(ctx, nil, roomID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
@ -837,8 +819,9 @@ func extractRoomVersionFromCreateEvent(event *gomatrixserverlib.Event) (
// "servers should not apply or send redactions to clients until both the redaction event and original event have been seen, and are valid." // "servers should not apply or send redactions to clients until both the redaction event and original event have been seen, and are valid."
// https://matrix.org/docs/spec/rooms/v3#authorization-rules-for-events // https://matrix.org/docs/spec/rooms/v3#authorization-rules-for-events
// These cases are: // These cases are:
// - This is a redaction event, redact the event it references if we know about it. // - This is a redaction event, redact the event it references if we know about it.
// - This is a normal event which may have been previously redacted. // - This is a normal event which may have been previously redacted.
//
// In the first case, check if we have the referenced event then apply the redaction, else store it // In the first case, check if we have the referenced event then apply the redaction, else store it
// in the redactions table with validated=FALSE. In the second case, check if there is a redaction for it: // in the redactions table with validated=FALSE. In the second case, check if there is a redaction for it:
// if there is then apply the redactions and set validated=TRUE. // if there is then apply the redactions and set validated=TRUE.