Skip to content
This repository was archived by the owner on Nov 25, 2024. It is now read-only.

Commit f4e7745

Browse files
authored
Speed up start up time by batch querying ACL events (#3334)
This should significantly speed up start up times on servers with many rooms.
1 parent 8f944f6 commit f4e7745

File tree

5 files changed

+43
-23
lines changed

5 files changed

+43
-23
lines changed

clientapi/clientapi_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,8 @@ func TestCapabilities(t *testing.T) {
958958
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
959959

960960
// Needed to create accounts
961-
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, caching.DisableMetrics)
961+
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
962+
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
962963
rsAPI.SetFederationAPI(nil, nil)
963964
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
964965
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.
@@ -1005,7 +1006,8 @@ func TestTurnserver(t *testing.T) {
10051006
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
10061007

10071008
// Needed to create accounts
1008-
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, caching.DisableMetrics)
1009+
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
1010+
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
10091011
rsAPI.SetFederationAPI(nil, nil)
10101012
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
10111013
//rsAPI.SetUserAPI(userAPI)
@@ -1103,7 +1105,8 @@ func Test3PID(t *testing.T) {
11031105
cm := sqlutil.NewConnectionManager(processCtx, cfg.Global.DatabaseOptions)
11041106

11051107
// Needed to create accounts
1106-
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, nil, caching.DisableMetrics)
1108+
caches := caching.NewRistrettoCache(128*1024*1024, time.Hour, caching.DisableMetrics)
1109+
rsAPI := roomserver.NewInternalAPI(processCtx, cfg, cm, &natsInstance, caches, caching.DisableMetrics)
11071110
rsAPI.SetFederationAPI(nil, nil)
11081111
userAPI := userapi.NewInternalAPI(processCtx, cfg, cm, &natsInstance, rsAPI, nil, caching.DisableMetrics, testIsBlacklistedOrBackingOff)
11091112
// We mostly need the rsAPI/userAPI for this test, so nil for other APIs etc.

roomserver/acls/acls.go

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"strings"
2424
"sync"
2525

26-
"github.com/matrix-org/dendrite/roomserver/types"
26+
"github.com/matrix-org/dendrite/roomserver/storage/tables"
2727
"github.com/matrix-org/gomatrixserverlib"
2828
"github.com/matrix-org/gomatrixserverlib/spec"
2929
"github.com/sirupsen/logrus"
@@ -34,10 +34,10 @@ const MRoomServerACL = "m.room.server_acl"
3434
type ServerACLDatabase interface {
3535
// GetKnownRooms returns a list of all rooms we know about.
3636
GetKnownRooms(ctx context.Context) ([]string, error)
37-
// GetStateEvent returns the state event of a given type for a given room with a given state key
38-
// If no event could be found, returns nil
39-
// If there was an issue during the retrieval, returns an error
40-
GetStateEvent(ctx context.Context, roomID, evType, stateKey string) (*types.HeaderedEvent, error)
37+
38+
// GetBulkStateContent returns all state events which match a given room ID and a given state key tuple. Both must be satisfied for a match.
39+
// If a tuple has the StateKey of '*' and allowWildcards=true then all state events with the EventType should be returned.
40+
GetBulkStateContent(ctx context.Context, roomIDs []string, tuples []gomatrixserverlib.StateKeyTuple, allowWildcards bool) ([]tables.StrippedEvent, error)
4141
}
4242

4343
type ServerACLs struct {
@@ -58,15 +58,14 @@ func NewServerACLs(db ServerACLDatabase) *ServerACLs {
5858
// For each room, let's see if we have a server ACL state event. If we
5959
// do then we'll process it into memory so that we have the regexes to
6060
// hand.
61-
for _, room := range rooms {
62-
state, err := db.GetStateEvent(ctx, room, MRoomServerACL, "")
63-
if err != nil {
64-
logrus.WithError(err).Errorf("Failed to get server ACLs for room %q", room)
65-
continue
66-
}
67-
if state != nil {
68-
acls.OnServerACLUpdate(state.PDU)
69-
}
61+
62+
events, err := db.GetBulkStateContent(ctx, rooms, []gomatrixserverlib.StateKeyTuple{{EventType: MRoomServerACL, StateKey: ""}}, false)
63+
if err != nil {
64+
logrus.WithError(err).Errorf("Failed to get server ACLs for all rooms: %q", err)
65+
}
66+
67+
for _, event := range events {
68+
acls.OnServerACLUpdate(event)
7069
}
7170
return acls
7271
}
@@ -90,9 +89,9 @@ func compileACLRegex(orig string) (*regexp.Regexp, error) {
9089
return regexp.Compile(escaped)
9190
}
9291

93-
func (s *ServerACLs) OnServerACLUpdate(state gomatrixserverlib.PDU) {
92+
func (s *ServerACLs) OnServerACLUpdate(strippedEvent tables.StrippedEvent) {
9493
acls := &serverACL{}
95-
if err := json.Unmarshal(state.Content(), &acls.ServerACL); err != nil {
94+
if err := json.Unmarshal([]byte(strippedEvent.ContentValue), &acls.ServerACL); err != nil {
9695
logrus.WithError(err).Errorf("Failed to unmarshal state content for server ACLs")
9796
return
9897
}
@@ -118,10 +117,10 @@ func (s *ServerACLs) OnServerACLUpdate(state gomatrixserverlib.PDU) {
118117
"allow_ip_literals": acls.AllowIPLiterals,
119118
"num_allowed": len(acls.allowedRegexes),
120119
"num_denied": len(acls.deniedRegexes),
121-
}).Debugf("Updating server ACLs for %q", state.RoomID())
120+
}).Debugf("Updating server ACLs for %q", strippedEvent.RoomID)
122121
s.aclsMutex.Lock()
123122
defer s.aclsMutex.Unlock()
124-
s.acls[state.RoomID().String()] = acls
123+
s.acls[strippedEvent.RoomID] = acls
125124
}
126125

127126
func (s *ServerACLs) IsServerBannedFromRoom(serverName spec.ServerName, roomID string) bool {

roomserver/internal/input/input_events.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"fmt"
2525
"time"
2626

27+
"github.com/matrix-org/dendrite/roomserver/storage/tables"
2728
"github.com/tidwall/gjson"
2829

2930
"github.com/matrix-org/gomatrixserverlib"
@@ -509,7 +510,13 @@ func (r *Inputer) processRoomEvent(
509510
logrus.WithError(err).Error("failed to get server ACLs")
510511
}
511512
if aclEvent != nil {
512-
r.ACLs.OnServerACLUpdate(aclEvent)
513+
strippedEvent := tables.StrippedEvent{
514+
RoomID: aclEvent.RoomID().String(),
515+
EventType: aclEvent.Type(),
516+
StateKey: *aclEvent.StateKey(),
517+
ContentValue: string(aclEvent.Content()),
518+
}
519+
r.ACLs.OnServerACLUpdate(strippedEvent)
513520
}
514521
}
515522
}

roomserver/producers/roomevent.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package producers
1717
import (
1818
"encoding/json"
1919

20+
"github.com/matrix-org/dendrite/roomserver/storage/tables"
2021
"github.com/nats-io/nats.go"
2122
log "github.com/sirupsen/logrus"
2223
"github.com/tidwall/gjson"
@@ -75,7 +76,13 @@ func (r *RoomEventProducer) ProduceRoomEvents(roomID string, updates []api.Outpu
7576

7677
if eventType == acls.MRoomServerACL && update.NewRoomEvent.Event.StateKeyEquals("") {
7778
ev := update.NewRoomEvent.Event.PDU
78-
defer r.ACLs.OnServerACLUpdate(ev)
79+
strippedEvent := tables.StrippedEvent{
80+
RoomID: ev.RoomID().String(),
81+
EventType: ev.Type(),
82+
StateKey: *ev.StateKey(),
83+
ContentValue: string(ev.Content()),
84+
}
85+
defer r.ACLs.OnServerACLUpdate(strippedEvent)
7986
}
8087
}
8188
logger.Tracef("Producing to topic '%s'", r.Topic)

roomserver/storage/tables/interface.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ func ExtractContentValue(ev *types.HeaderedEvent) string {
235235
key = "topic"
236236
case "m.room.guest_access":
237237
key = "guest_access"
238+
case "m.room.server_acl":
239+
// We need the entire content and not only one key, so we can use it
240+
// on startup to generate the ACLs. This is merely a workaround.
241+
return string(content)
238242
}
239243
result := gjson.GetBytes(content, key)
240244
if !result.Exists() {

0 commit comments

Comments
 (0)