mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-08-03 14:42:47 +00:00
Fulltext implementation using Bleve (#2675)
Based on #2480 This actually indexes events based on their event type. They are removed from the index if we receive a `m.room.redaction` event on the `OutputRoomEvent` stream. An admin endpoint is added to reindex all existing events. Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
parent
6c67552bf9
commit
87be32ca26
22 changed files with 680 additions and 53 deletions
|
@ -17,14 +17,18 @@ package consumers
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/sirupsen/logrus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/matrix-org/dendrite/internal/eventutil"
|
||||
"github.com/matrix-org/dendrite/internal/fulltext"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/setup/jetstream"
|
||||
"github.com/matrix-org/dendrite/setup/process"
|
||||
|
@ -35,14 +39,18 @@ import (
|
|||
|
||||
// OutputClientDataConsumer consumes events that originated in the client API server.
|
||||
type OutputClientDataConsumer struct {
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
durable string
|
||||
topic string
|
||||
db storage.Database
|
||||
stream types.StreamProvider
|
||||
notifier *notifier.Notifier
|
||||
serverName gomatrixserverlib.ServerName
|
||||
ctx context.Context
|
||||
jetstream nats.JetStreamContext
|
||||
nats *nats.Conn
|
||||
durable string
|
||||
topic string
|
||||
topicReIndex string
|
||||
db storage.Database
|
||||
stream types.StreamProvider
|
||||
notifier *notifier.Notifier
|
||||
serverName gomatrixserverlib.ServerName
|
||||
fts *fulltext.Search
|
||||
cfg *config.SyncAPI
|
||||
}
|
||||
|
||||
// NewOutputClientDataConsumer creates a new OutputClientData consumer. Call Start() to begin consuming from room servers.
|
||||
|
@ -50,24 +58,93 @@ func NewOutputClientDataConsumer(
|
|||
process *process.ProcessContext,
|
||||
cfg *config.SyncAPI,
|
||||
js nats.JetStreamContext,
|
||||
nats *nats.Conn,
|
||||
store storage.Database,
|
||||
notifier *notifier.Notifier,
|
||||
stream types.StreamProvider,
|
||||
fts *fulltext.Search,
|
||||
) *OutputClientDataConsumer {
|
||||
return &OutputClientDataConsumer{
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputClientData),
|
||||
durable: cfg.Matrix.JetStream.Durable("SyncAPIAccountDataConsumer"),
|
||||
db: store,
|
||||
notifier: notifier,
|
||||
stream: stream,
|
||||
serverName: cfg.Matrix.ServerName,
|
||||
ctx: process.Context(),
|
||||
jetstream: js,
|
||||
topic: cfg.Matrix.JetStream.Prefixed(jetstream.OutputClientData),
|
||||
topicReIndex: cfg.Matrix.JetStream.Prefixed(jetstream.InputFulltextReindex),
|
||||
durable: cfg.Matrix.JetStream.Durable("SyncAPIAccountDataConsumer"),
|
||||
nats: nats,
|
||||
db: store,
|
||||
notifier: notifier,
|
||||
stream: stream,
|
||||
serverName: cfg.Matrix.ServerName,
|
||||
fts: fts,
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// Start consuming from room servers
|
||||
func (s *OutputClientDataConsumer) Start() error {
|
||||
_, err := s.nats.Subscribe(s.topicReIndex, func(msg *nats.Msg) {
|
||||
if err := msg.Ack(); err != nil {
|
||||
return
|
||||
}
|
||||
if !s.cfg.Fulltext.Enabled {
|
||||
logrus.Warn("Fulltext indexing is disabled")
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
logrus.Debugf("Starting to index events")
|
||||
var offset int
|
||||
start := time.Now()
|
||||
count := 0
|
||||
var id int64 = 0
|
||||
for {
|
||||
evs, err := s.db.ReIndex(ctx, 1000, id)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("unable to get events to index")
|
||||
return
|
||||
}
|
||||
if len(evs) == 0 {
|
||||
break
|
||||
}
|
||||
logrus.Debugf("Indexing %d events", len(evs))
|
||||
elements := make([]fulltext.IndexElement, 0, len(evs))
|
||||
|
||||
for streamPos, ev := range evs {
|
||||
id = streamPos
|
||||
e := fulltext.IndexElement{
|
||||
EventID: ev.EventID(),
|
||||
RoomID: ev.RoomID(),
|
||||
StreamPosition: streamPos,
|
||||
}
|
||||
e.SetContentType(ev.Type())
|
||||
|
||||
switch ev.Type() {
|
||||
case "m.room.message":
|
||||
e.Content = gjson.GetBytes(ev.Content(), "body").String()
|
||||
case gomatrixserverlib.MRoomName:
|
||||
e.Content = gjson.GetBytes(ev.Content(), "name").String()
|
||||
case gomatrixserverlib.MRoomTopic:
|
||||
e.Content = gjson.GetBytes(ev.Content(), "topic").String()
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.TrimSpace(e.Content) == "" {
|
||||
continue
|
||||
}
|
||||
elements = append(elements, e)
|
||||
}
|
||||
if err = s.fts.Index(elements...); err != nil {
|
||||
logrus.WithError(err).Error("unable to index events")
|
||||
continue
|
||||
}
|
||||
offset += len(evs)
|
||||
count += len(elements)
|
||||
}
|
||||
logrus.Debugf("Indexed %d events in %v", count, time.Since(start))
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jetstream.JetStreamConsumer(
|
||||
s.ctx, s.jetstream, s.topic, s.durable, 1,
|
||||
s.onMessage, nats.DeliverAll(), nats.ManualAck(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue