mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-26 15:08:28 +00:00
Try to increase roomserver parallelisation
This commit is contained in:
parent
a6f7e83596
commit
8e5ad6e554
2 changed files with 31 additions and 82 deletions
|
@ -19,17 +19,16 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/Shopify/sarama"
|
"github.com/Shopify/sarama"
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/hooks"
|
"github.com/matrix-org/dendrite/internal/hooks"
|
||||||
"github.com/matrix-org/dendrite/roomserver/acls"
|
"github.com/matrix-org/dendrite/roomserver/acls"
|
||||||
"github.com/matrix-org/dendrite/roomserver/api"
|
"github.com/matrix-org/dendrite/roomserver/api"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage"
|
"github.com/matrix-org/dendrite/roomserver/storage"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"go.uber.org/atomic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Inputer struct {
|
type Inputer struct {
|
||||||
|
@ -38,41 +37,7 @@ type Inputer struct {
|
||||||
ServerName gomatrixserverlib.ServerName
|
ServerName gomatrixserverlib.ServerName
|
||||||
ACLs *acls.ServerACLs
|
ACLs *acls.ServerACLs
|
||||||
OutputRoomEventTopic string
|
OutputRoomEventTopic string
|
||||||
|
roomMutexes internal.MutexByRoom
|
||||||
workers sync.Map // room ID -> *inputWorker
|
|
||||||
}
|
|
||||||
|
|
||||||
type inputTask struct {
|
|
||||||
ctx context.Context
|
|
||||||
event *api.InputRoomEvent
|
|
||||||
wg *sync.WaitGroup
|
|
||||||
err error // written back by worker, only safe to read when all tasks are done
|
|
||||||
}
|
|
||||||
|
|
||||||
type inputWorker struct {
|
|
||||||
r *Inputer
|
|
||||||
running atomic.Bool
|
|
||||||
input chan *inputTask
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guarded by a CAS on w.running
|
|
||||||
func (w *inputWorker) start() {
|
|
||||||
defer w.running.Store(false)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case task := <-w.input:
|
|
||||||
hooks.Run(hooks.KindNewEventReceived, task.event.Event)
|
|
||||||
_, task.err = w.r.processRoomEvent(task.ctx, task.event)
|
|
||||||
if task.err == nil {
|
|
||||||
hooks.Run(hooks.KindNewEventPersisted, task.event.Event)
|
|
||||||
} else {
|
|
||||||
sentry.CaptureException(task.err)
|
|
||||||
}
|
|
||||||
task.wg.Done()
|
|
||||||
case <-time.After(time.Second * 5):
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteOutputEvents implements OutputRoomEventWriter
|
// WriteOutputEvents implements OutputRoomEventWriter
|
||||||
|
@ -123,57 +88,38 @@ func (r *Inputer) InputRoomEvents(
|
||||||
request *api.InputRoomEventsRequest,
|
request *api.InputRoomEventsRequest,
|
||||||
response *api.InputRoomEventsResponse,
|
response *api.InputRoomEventsResponse,
|
||||||
) {
|
) {
|
||||||
// Create a wait group. Each task that we dispatch will call Done on
|
ctx := context.Background()
|
||||||
// this wait group so that we know when all of our events have been
|
|
||||||
// processed.
|
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
|
errs := make(chan error)
|
||||||
wg.Add(len(request.InputRoomEvents))
|
wg.Add(len(request.InputRoomEvents))
|
||||||
tasks := make([]*inputTask, len(request.InputRoomEvents))
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(errs)
|
||||||
|
}()
|
||||||
|
|
||||||
for i, e := range request.InputRoomEvents {
|
for _, e := range request.InputRoomEvents {
|
||||||
// Work out if we are running per-room workers or if we're just doing
|
go func(e *api.InputRoomEvent) {
|
||||||
// it on a global basis (e.g. SQLite).
|
defer wg.Done()
|
||||||
roomID := "global"
|
hooks.Run(hooks.KindNewEventReceived, e.Event)
|
||||||
if r.DB.SupportsConcurrentRoomInputs() {
|
_, err := r.processRoomEvent(ctx, e)
|
||||||
roomID = e.Event.RoomID()
|
if err == nil {
|
||||||
}
|
hooks.Run(hooks.KindNewEventPersisted, e.Event)
|
||||||
|
} else {
|
||||||
// Look up the worker, or create it if it doesn't exist. This channel
|
sentry.CaptureException(err)
|
||||||
// is buffered to reduce the chance that we'll be blocked by another
|
select {
|
||||||
// room - the channel will be quite small as it's just pointer types.
|
case errs <- err:
|
||||||
w, _ := r.workers.LoadOrStore(roomID, &inputWorker{
|
default:
|
||||||
r: r,
|
}
|
||||||
input: make(chan *inputTask, 32),
|
}
|
||||||
})
|
}(&e)
|
||||||
worker := w.(*inputWorker)
|
|
||||||
|
|
||||||
// Create a task. This contains the input event and a reference to
|
|
||||||
// the wait group, so that the worker can notify us when this specific
|
|
||||||
// task has been finished.
|
|
||||||
tasks[i] = &inputTask{
|
|
||||||
ctx: context.Background(),
|
|
||||||
event: &request.InputRoomEvents[i],
|
|
||||||
wg: wg,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the task to the worker.
|
|
||||||
if worker.running.CAS(false, true) {
|
|
||||||
go worker.start()
|
|
||||||
}
|
|
||||||
worker.input <- tasks[i]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for all of the workers to return results about our tasks.
|
for err := range errs {
|
||||||
wg.Wait()
|
if err != nil {
|
||||||
|
response.ErrMsg = err.Error()
|
||||||
// If any of the tasks returned an error, we should probably report
|
_, rejected := err.(*gomatrixserverlib.NotAllowed)
|
||||||
// that back to the caller.
|
|
||||||
for _, task := range tasks {
|
|
||||||
if task.err != nil {
|
|
||||||
response.ErrMsg = task.err.Error()
|
|
||||||
_, rejected := task.err.(*gomatrixserverlib.NotAllowed)
|
|
||||||
response.NotAllowed = rejected
|
response.NotAllowed = rejected
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,6 +288,9 @@ func (u *latestEventsUpdater) calculateLatest(
|
||||||
newEvent *gomatrixserverlib.Event,
|
newEvent *gomatrixserverlib.Event,
|
||||||
newStateAndRef types.StateAtEventAndReference,
|
newStateAndRef types.StateAtEventAndReference,
|
||||||
) (bool, error) {
|
) (bool, error) {
|
||||||
|
u.api.roomMutexes.Lock(u.event.EventID())
|
||||||
|
defer u.api.roomMutexes.Unlock(u.event.EventID())
|
||||||
|
|
||||||
// First of all, get a list of all of the events in our current
|
// First of all, get a list of all of the events in our current
|
||||||
// set of forward extremities.
|
// set of forward extremities.
|
||||||
existingRefs := make(map[string]*types.StateAtEventAndReference)
|
existingRefs := make(map[string]*types.StateAtEventAndReference)
|
||||||
|
|
Loading…
Reference in a new issue