aboutsummaryrefslogtreecommitdiff
path: root/roomserver
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2022-08-18 10:37:47 +0100
committerGitHub <noreply@github.com>2022-08-18 10:37:47 +0100
commit59bc0a6f4ed0324da0387118e1761b4551aaf103 (patch)
tree8a0708cf274aae31cb8cb1a9697adb9f96960e57 /roomserver
parent8d9c8f11c5c5673d48b8e5308e1f565927bdd341 (diff)
Reprocess rejected input events (#2647)
* Reprocess outliers that were previously rejected * Might as well do all events this way * More useful errors * Fix queries * Tweak condition * Don't wrap errors * Report more useful error * Flatten error on `r.Queryer.QueryStateAfterEvents` * Some more debug logging * Flatten error in `QueryRestrictedJoinAllowed` * Revert "Flatten error in `QueryRestrictedJoinAllowed`" This reverts commit 1238b4184c30e0c31ffb0f364806fa1275aba483. * Tweak `QueryStateAfterEvents` * Handle MissingStateError too * Scope to room * Clean up * Fix the error * Only apply rejection check to outliers
Diffstat (limited to 'roomserver')
-rw-r--r--roomserver/internal/input/input_events.go47
-rw-r--r--roomserver/internal/query/query.go13
-rw-r--r--roomserver/storage/interface.go2
-rw-r--r--roomserver/storage/postgres/events_table.go13
-rw-r--r--roomserver/storage/shared/storage.go4
-rw-r--r--roomserver/storage/sqlite3/events_table.go13
-rw-r--r--roomserver/storage/tables/interface.go1
7 files changed, 65 insertions, 28 deletions
diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go
index 81541260..53ccd597 100644
--- a/roomserver/internal/input/input_events.go
+++ b/roomserver/internal/input/input_events.go
@@ -17,8 +17,8 @@
package input
import (
- "bytes"
"context"
+ "database/sql"
"fmt"
"time"
@@ -107,28 +107,6 @@ func (r *Inputer) processRoomEvent(
})
}
- // if we have already got this event then do not process it again, if the input kind is an outlier.
- // Outliers contain no extra information which may warrant a re-processing.
- if input.Kind == api.KindOutlier {
- evs, err2 := r.DB.EventsFromIDs(ctx, []string{event.EventID()})
- if err2 == nil && len(evs) == 1 {
- // check hash matches if we're on early room versions where the event ID was a random string
- idFormat, err2 := headered.RoomVersion.EventIDFormat()
- if err2 == nil {
- switch idFormat {
- case gomatrixserverlib.EventIDFormatV1:
- if bytes.Equal(event.EventReference().EventSHA256, evs[0].EventReference().EventSHA256) {
- logger.Debugf("Already processed event; ignoring")
- return nil
- }
- default:
- logger.Debugf("Already processed event; ignoring")
- return nil
- }
- }
- }
- }
-
// Don't waste time processing the event if the room doesn't exist.
// A room entry locally will only be created in response to a create
// event.
@@ -141,6 +119,29 @@ func (r *Inputer) processRoomEvent(
return fmt.Errorf("room %s does not exist for event %s", event.RoomID(), event.EventID())
}
+ // If we already know about this outlier and it hasn't been rejected
+ // then we won't attempt to reprocess it. If it was rejected or has now
+ // arrived as a different kind of event, then we can attempt to reprocess,
+ // in case we have learned something new or need to weave the event into
+ // the DAG now.
+ if input.Kind == api.KindOutlier && roomInfo != nil {
+ wasRejected, werr := r.DB.IsEventRejected(ctx, roomInfo.RoomNID, event.EventID())
+ switch {
+ case werr == sql.ErrNoRows:
+ // We haven't seen this event before so continue.
+ case werr != nil:
+ // Something has gone wrong trying to find out if we rejected
+ // this event already.
+ logger.WithError(werr).Errorf("Failed to check if event %q is already seen", event.EventID())
+ return werr
+ case !wasRejected:
+ // We've seen this event before and it wasn't rejected so we
+ // should ignore it.
+ logger.Debugf("Already processed event %q, ignoring", event.EventID())
+ return nil
+ }
+ }
+
var missingAuth, missingPrev bool
serverRes := &fedapi.QueryJoinedHostServerNamesInRoomResponse{}
if !isCreateEvent {
diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go
index f3061c22..f5d8c2d4 100644
--- a/roomserver/internal/query/query.go
+++ b/roomserver/internal/query/query.go
@@ -72,13 +72,10 @@ func (r *Queryer) QueryStateAfterEvents(
prevStates, err := r.DB.StateAtEventIDs(ctx, request.PrevEventIDs)
if err != nil {
- switch err.(type) {
- case types.MissingEventError:
- util.GetLogger(ctx).Errorf("QueryStateAfterEvents: MissingEventError: %s", err)
+ if _, ok := err.(types.MissingEventError); ok {
return nil
- default:
- return err
}
+ return err
}
response.PrevEventsExist = true
@@ -95,6 +92,12 @@ func (r *Queryer) QueryStateAfterEvents(
)
}
if err != nil {
+ if _, ok := err.(types.MissingEventError); ok {
+ return nil
+ }
+ if _, ok := err.(types.MissingStateError); ok {
+ return nil
+ }
return err
}
diff --git a/roomserver/storage/interface.go b/roomserver/storage/interface.go
index b12025c4..5c068873 100644
--- a/roomserver/storage/interface.go
+++ b/roomserver/storage/interface.go
@@ -94,6 +94,8 @@ type Database interface {
// Opens and returns a room updater, which locks the room and opens a transaction.
// The GetRoomUpdater must have Commit or Rollback called on it if this doesn't return an error.
// If this returns an error then no further action is required.
+ // IsEventRejected returns true if the event is known and rejected.
+ IsEventRejected(ctx context.Context, roomNID types.RoomNID, eventID string) (rejected bool, err error)
GetRoomUpdater(ctx context.Context, roomInfo *types.RoomInfo) (*shared.RoomUpdater, error)
// Look up event references for the latest events in the room and the current state snapshot.
// Returns the latest events, the current state and the maximum depth of the latest events plus 1.
diff --git a/roomserver/storage/postgres/events_table.go b/roomserver/storage/postgres/events_table.go
index a4d05756..c7748d2b 100644
--- a/roomserver/storage/postgres/events_table.go
+++ b/roomserver/storage/postgres/events_table.go
@@ -136,6 +136,9 @@ const selectMaxEventDepthSQL = "" +
const selectRoomNIDsForEventNIDsSQL = "" +
"SELECT event_nid, room_nid FROM roomserver_events WHERE event_nid = ANY($1)"
+const selectEventRejectedSQL = "" +
+ "SELECT is_rejected FROM roomserver_events WHERE room_nid = $1 AND event_id = $2"
+
type eventStatements struct {
insertEventStmt *sql.Stmt
selectEventStmt *sql.Stmt
@@ -153,6 +156,7 @@ type eventStatements struct {
bulkSelectUnsentEventNIDStmt *sql.Stmt
selectMaxEventDepthStmt *sql.Stmt
selectRoomNIDsForEventNIDsStmt *sql.Stmt
+ selectEventRejectedStmt *sql.Stmt
}
func CreateEventsTable(db *sql.DB) error {
@@ -180,6 +184,7 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
{&s.bulkSelectUnsentEventNIDStmt, bulkSelectUnsentEventNIDSQL},
{&s.selectMaxEventDepthStmt, selectMaxEventDepthSQL},
{&s.selectRoomNIDsForEventNIDsStmt, selectRoomNIDsForEventNIDsSQL},
+ {&s.selectEventRejectedStmt, selectEventRejectedSQL},
}.Prepare(db)
}
@@ -540,3 +545,11 @@ func eventNIDsAsArray(eventNIDs []types.EventNID) pq.Int64Array {
}
return nids
}
+
+func (s *eventStatements) SelectEventRejected(
+ ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, eventID string,
+) (rejected bool, err error) {
+ stmt := sqlutil.TxStmt(txn, s.selectEventRejectedStmt)
+ err = stmt.QueryRowContext(ctx, roomNID, eventID).Scan(&rejected)
+ return
+}
diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go
index cbf9c8b2..4f92adf1 100644
--- a/roomserver/storage/shared/storage.go
+++ b/roomserver/storage/shared/storage.go
@@ -567,6 +567,10 @@ func (d *Database) GetRoomUpdater(
return updater, err
}
+func (d *Database) IsEventRejected(ctx context.Context, roomNID types.RoomNID, eventID string) (bool, error) {
+ return d.EventsTable.SelectEventRejected(ctx, nil, roomNID, eventID)
+}
+
func (d *Database) StoreEvent(
ctx context.Context, event *gomatrixserverlib.Event,
authEventNIDs []types.EventNID, isRejected bool,
diff --git a/roomserver/storage/sqlite3/events_table.go b/roomserver/storage/sqlite3/events_table.go
index 1dda34c3..174e3a9a 100644
--- a/roomserver/storage/sqlite3/events_table.go
+++ b/roomserver/storage/sqlite3/events_table.go
@@ -109,6 +109,9 @@ const selectMaxEventDepthSQL = "" +
const selectRoomNIDsForEventNIDsSQL = "" +
"SELECT event_nid, room_nid FROM roomserver_events WHERE event_nid IN ($1)"
+const selectEventRejectedSQL = "" +
+ "SELECT is_rejected FROM roomserver_events WHERE room_nid = $1 AND event_id = $2"
+
type eventStatements struct {
db *sql.DB
insertEventStmt *sql.Stmt
@@ -122,6 +125,7 @@ type eventStatements struct {
bulkSelectStateAtEventAndReferenceStmt *sql.Stmt
bulkSelectEventReferenceStmt *sql.Stmt
bulkSelectEventIDStmt *sql.Stmt
+ selectEventRejectedStmt *sql.Stmt
//bulkSelectEventNIDStmt *sql.Stmt
//bulkSelectUnsentEventNIDStmt *sql.Stmt
//selectRoomNIDsForEventNIDsStmt *sql.Stmt
@@ -152,6 +156,7 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
//{&s.bulkSelectEventNIDStmt, bulkSelectEventNIDSQL},
//{&s.bulkSelectUnsentEventNIDStmt, bulkSelectUnsentEventNIDSQL},
//{&s.selectRoomNIDForEventNIDStmt, selectRoomNIDForEventNIDSQL},
+ {&s.selectEventRejectedStmt, selectEventRejectedSQL},
}.Prepare(db)
}
@@ -614,3 +619,11 @@ func eventNIDsAsArray(eventNIDs []types.EventNID) string {
b, _ := json.Marshal(eventNIDs)
return string(b)
}
+
+func (s *eventStatements) SelectEventRejected(
+ ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, eventID string,
+) (rejected bool, err error) {
+ stmt := sqlutil.TxStmt(txn, s.selectEventRejectedStmt)
+ err = stmt.QueryRowContext(ctx, roomNID, eventID).Scan(&rejected)
+ return
+}
diff --git a/roomserver/storage/tables/interface.go b/roomserver/storage/tables/interface.go
index 0bc389b8..ed67c43d 100644
--- a/roomserver/storage/tables/interface.go
+++ b/roomserver/storage/tables/interface.go
@@ -66,6 +66,7 @@ type Events interface {
BulkSelectUnsentEventNID(ctx context.Context, txn *sql.Tx, eventIDs []string) (map[string]types.EventNID, error)
SelectMaxEventDepth(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) (int64, error)
SelectRoomNIDsForEventNIDs(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) (roomNIDs map[types.EventNID]types.RoomNID, err error)
+ SelectEventRejected(ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, eventID string) (rejected bool, err error)
}
type Rooms interface {