mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-25 22:48:27 +00:00
Drop reference_sha
column (#3083)
Companion PR to https://github.com/matrix-org/gomatrixserverlib/pull/383
This commit is contained in:
parent
5d6221d191
commit
11b557097c
29 changed files with 299 additions and 227 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -75,3 +75,6 @@ docs/_site
|
||||||
|
|
||||||
media_store/
|
media_store/
|
||||||
build
|
build
|
||||||
|
|
||||||
|
# golang workspaces
|
||||||
|
go.work*
|
|
@ -22,7 +22,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMonolithStarts(t *testing.T) {
|
func TestMonolithStarts(t *testing.T) {
|
||||||
monolith := DendriteMonolith{}
|
monolith := DendriteMonolith{
|
||||||
|
StorageDirectory: t.TempDir(),
|
||||||
|
CacheDirectory: t.TempDir(),
|
||||||
|
}
|
||||||
monolith.Start()
|
monolith.Start()
|
||||||
monolith.PublicKey()
|
monolith.PublicKey()
|
||||||
monolith.Stop()
|
monolith.Stop()
|
||||||
|
@ -60,7 +63,10 @@ func TestMonolithSetRelayServers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
monolith := DendriteMonolith{}
|
monolith := DendriteMonolith{
|
||||||
|
StorageDirectory: t.TempDir(),
|
||||||
|
CacheDirectory: t.TempDir(),
|
||||||
|
}
|
||||||
monolith.Start()
|
monolith.Start()
|
||||||
|
|
||||||
inputRelays := tc.relays
|
inputRelays := tc.relays
|
||||||
|
|
|
@ -470,7 +470,7 @@ func createRoom(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
builder.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
|
builder.PrevEvents = []string{builtEvents[i-1].EventID()}
|
||||||
}
|
}
|
||||||
var ev gomatrixserverlib.PDU
|
var ev gomatrixserverlib.PDU
|
||||||
if err = builder.AddAuthEvents(&authEvents); err != nil {
|
if err = builder.AddAuthEvents(&authEvents); err != nil {
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -22,7 +22,7 @@ require (
|
||||||
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
|
github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230523164045-3fddabebb511
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230524095531-95ba6c68efb6
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
|
||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -323,8 +323,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw
|
||||||
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230523164045-3fddabebb511 h1:om6z/WEVZMxZfgtiyfp5r5ubAObGMyRrnlVD07gIRY4=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230524095531-95ba6c68efb6 h1:FQpdh/KGCCQJytz4GAdG6pbx3DJ1HNzdKFc/BCZ0hP0=
|
||||||
github.com/matrix-org/gomatrixserverlib v0.0.0-20230523164045-3fddabebb511/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
github.com/matrix-org/gomatrixserverlib v0.0.0-20230524095531-95ba6c68efb6/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A=
|
||||||
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
|
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ=
|
||||||
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
|
||||||
|
|
|
@ -129,18 +129,12 @@ func addPrevEventsToEvent(
|
||||||
return ErrRoomNoExists{}
|
return ErrRoomNoExists{}
|
||||||
}
|
}
|
||||||
|
|
||||||
verImpl, err := gomatrixserverlib.GetRoomVersion(queryRes.RoomVersion)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("GetRoomVersion: %w", err)
|
|
||||||
}
|
|
||||||
eventFormat := verImpl.EventFormat()
|
|
||||||
|
|
||||||
builder.Depth = queryRes.Depth
|
builder.Depth = queryRes.Depth
|
||||||
|
|
||||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
||||||
|
|
||||||
for i := range queryRes.StateEvents {
|
for i := range queryRes.StateEvents {
|
||||||
err = authEvents.AddEvent(queryRes.StateEvents[i].PDU)
|
err := authEvents.AddEvent(queryRes.StateEvents[i].PDU)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("authEvents.AddEvent: %w", err)
|
return fmt.Errorf("authEvents.AddEvent: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -151,22 +145,7 @@ func addPrevEventsToEvent(
|
||||||
return fmt.Errorf("eventsNeeded.AuthEventReferences: %w", err)
|
return fmt.Errorf("eventsNeeded.AuthEventReferences: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
truncAuth, truncPrev := truncateAuthAndPrevEvents(refs, queryRes.LatestEvents)
|
builder.AuthEvents, builder.PrevEvents = truncateAuthAndPrevEvents(refs, queryRes.LatestEvents)
|
||||||
switch eventFormat {
|
|
||||||
case gomatrixserverlib.EventFormatV1:
|
|
||||||
builder.AuthEvents = truncAuth
|
|
||||||
builder.PrevEvents = truncPrev
|
|
||||||
case gomatrixserverlib.EventFormatV2:
|
|
||||||
v2AuthRefs, v2PrevRefs := []string{}, []string{}
|
|
||||||
for _, ref := range truncAuth {
|
|
||||||
v2AuthRefs = append(v2AuthRefs, ref.EventID)
|
|
||||||
}
|
|
||||||
for _, ref := range truncPrev {
|
|
||||||
v2PrevRefs = append(v2PrevRefs, ref.EventID)
|
|
||||||
}
|
|
||||||
builder.AuthEvents = v2AuthRefs
|
|
||||||
builder.PrevEvents = v2PrevRefs
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -176,8 +155,8 @@ func addPrevEventsToEvent(
|
||||||
// NOTSPEC: The limits here feel a bit arbitrary but they are currently
|
// NOTSPEC: The limits here feel a bit arbitrary but they are currently
|
||||||
// here because of https://github.com/matrix-org/matrix-doc/issues/2307
|
// here because of https://github.com/matrix-org/matrix-doc/issues/2307
|
||||||
// and because Synapse will just drop events that don't comply.
|
// and because Synapse will just drop events that don't comply.
|
||||||
func truncateAuthAndPrevEvents(auth, prev []gomatrixserverlib.EventReference) (
|
func truncateAuthAndPrevEvents(auth, prev []string) (
|
||||||
truncAuth, truncPrev []gomatrixserverlib.EventReference,
|
truncAuth, truncPrev []string,
|
||||||
) {
|
) {
|
||||||
truncAuth, truncPrev = auth, prev
|
truncAuth, truncPrev = auth, prev
|
||||||
if len(truncAuth) > 10 {
|
if len(truncAuth) > 10 {
|
||||||
|
|
|
@ -49,7 +49,7 @@ type QueryLatestEventsAndStateResponse struct {
|
||||||
RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
|
RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
|
||||||
// The latest events in the room.
|
// The latest events in the room.
|
||||||
// These are used to set the prev_events when sending an event.
|
// These are used to set the prev_events when sending an event.
|
||||||
LatestEvents []gomatrixserverlib.EventReference `json:"latest_events"`
|
LatestEvents []string `json:"latest_events"`
|
||||||
// The state events requested.
|
// The state events requested.
|
||||||
// This list will be in an arbitrary order.
|
// This list will be in an arbitrary order.
|
||||||
// These are used to set the auth_events when sending an event.
|
// These are used to set the auth_events when sending an event.
|
||||||
|
|
|
@ -883,9 +883,7 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
|
||||||
Origin: senderDomain,
|
Origin: senderDomain,
|
||||||
SendAsServer: string(senderDomain),
|
SendAsServer: string(senderDomain),
|
||||||
})
|
})
|
||||||
prevEvents = []gomatrixserverlib.EventReference{
|
prevEvents = []string{event.EventID()}
|
||||||
event.EventReference(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputReq := &api.InputRoomEventsRequest{
|
inputReq := &api.InputRoomEventsRequest{
|
||||||
|
|
|
@ -154,8 +154,8 @@ func (u *latestEventsUpdater) doUpdateLatestEvents() error {
|
||||||
extremitiesChanged, err := u.calculateLatest(
|
extremitiesChanged, err := u.calculateLatest(
|
||||||
u.oldLatest, u.event,
|
u.oldLatest, u.event,
|
||||||
types.StateAtEventAndReference{
|
types.StateAtEventAndReference{
|
||||||
EventReference: u.event.EventReference(),
|
EventID: u.event.EventID(),
|
||||||
StateAtEvent: u.stateAtEvent,
|
StateAtEvent: u.stateAtEvent,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -349,7 +349,7 @@ func (u *latestEventsUpdater) calculateLatest(
|
||||||
// If the "new" event is already referenced by an existing event
|
// If the "new" event is already referenced by an existing event
|
||||||
// then do nothing - it's not a candidate to be a new extremity if
|
// then do nothing - it's not a candidate to be a new extremity if
|
||||||
// it has been referenced.
|
// it has been referenced.
|
||||||
if referenced, err := u.updater.IsReferenced(newEvent.EventReference()); err != nil {
|
if referenced, err := u.updater.IsReferenced(newEvent.EventID()); err != nil {
|
||||||
return false, fmt.Errorf("u.updater.IsReferenced(new): %w", err)
|
return false, fmt.Errorf("u.updater.IsReferenced(new): %w", err)
|
||||||
} else if referenced {
|
} else if referenced {
|
||||||
u.latest = oldLatest
|
u.latest = oldLatest
|
||||||
|
@ -360,7 +360,7 @@ func (u *latestEventsUpdater) calculateLatest(
|
||||||
// have entries in the previous events table. If they do then we
|
// have entries in the previous events table. If they do then we
|
||||||
// will no longer include them as forward extremities.
|
// will no longer include them as forward extremities.
|
||||||
for k, l := range existingRefs {
|
for k, l := range existingRefs {
|
||||||
referenced, err := u.updater.IsReferenced(l.EventReference)
|
referenced, err := u.updater.IsReferenced(l.EventID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("u.updater.IsReferenced: %w", err)
|
return false, fmt.Errorf("u.updater.IsReferenced: %w", err)
|
||||||
} else if referenced {
|
} else if referenced {
|
||||||
|
|
|
@ -520,9 +520,9 @@ func (t *missingStateReq) getMissingEvents(ctx context.Context, e gomatrixserver
|
||||||
return nil, false, false, fmt.Errorf("t.DB.LatestEventIDs: %w", err)
|
return nil, false, false, fmt.Errorf("t.DB.LatestEventIDs: %w", err)
|
||||||
}
|
}
|
||||||
latestEvents := make([]string, len(latest))
|
latestEvents := make([]string, len(latest))
|
||||||
for i, ev := range latest {
|
for i := range latest {
|
||||||
latestEvents[i] = ev.EventID
|
latestEvents[i] = latest[i]
|
||||||
t.hadEvent(ev.EventID)
|
t.hadEvent(latest[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
var missingResp *fclient.RespMissingEvents
|
var missingResp *fclient.RespMissingEvents
|
||||||
|
|
|
@ -131,9 +131,7 @@ func (r *Admin) PerformAdminEvacuateRoom(
|
||||||
SendAsServer: string(senderDomain),
|
SendAsServer: string(senderDomain),
|
||||||
})
|
})
|
||||||
affected = append(affected, stateKey)
|
affected = append(affected, stateKey)
|
||||||
prevEvents = []gomatrixserverlib.EventReference{
|
prevEvents = []string{event.EventID()}
|
||||||
event.EventReference(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputReq := &api.InputRoomEventsRequest{
|
inputReq := &api.InputRoomEventsRequest{
|
||||||
|
@ -253,9 +251,9 @@ func (r *Admin) PerformAdminDownloadState(
|
||||||
|
|
||||||
for _, fwdExtremity := range fwdExtremities {
|
for _, fwdExtremity := range fwdExtremities {
|
||||||
var state gomatrixserverlib.StateResponse
|
var state gomatrixserverlib.StateResponse
|
||||||
state, err = r.Inputer.FSAPI.LookupState(ctx, r.Inputer.ServerName, serverName, roomID, fwdExtremity.EventID, roomInfo.RoomVersion)
|
state, err = r.Inputer.FSAPI.LookupState(ctx, r.Inputer.ServerName, serverName, roomID, fwdExtremity, roomInfo.RoomVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("r.Inputer.FSAPI.LookupState (%q): %s", fwdExtremity.EventID, err)
|
return fmt.Errorf("r.Inputer.FSAPI.LookupState (%q): %s", fwdExtremity, err)
|
||||||
}
|
}
|
||||||
for _, authEvent := range state.GetAuthEvents().UntrustedEvents(roomInfo.RoomVersion) {
|
for _, authEvent := range state.GetAuthEvents().UntrustedEvents(roomInfo.RoomVersion) {
|
||||||
if err = gomatrixserverlib.VerifyEventSignatures(ctx, authEvent, r.Inputer.KeyRing); err != nil {
|
if err = gomatrixserverlib.VerifyEventSignatures(ctx, authEvent, r.Inputer.KeyRing); err != nil {
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (r *InboundPeeker) PerformInboundPeek(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
latestEvents, err := r.DB.EventsFromIDs(ctx, info, []string{latestEventRefs[0].EventID})
|
latestEvents, err := r.DB.EventsFromIDs(ctx, info, []string{latestEventRefs[0]})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,7 +471,7 @@ func (r *Upgrader) sendInitialEvents(ctx context.Context, evTime time.Time, user
|
||||||
return fmt.Errorf("failed to set content of new %q event: %w", proto.Type, err)
|
return fmt.Errorf("failed to set content of new %q event: %w", proto.Type, err)
|
||||||
}
|
}
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
proto.PrevEvents = []gomatrixserverlib.EventReference{builtEvents[i-1].EventReference()}
|
proto.PrevEvents = []string{builtEvents[i-1].EventID()}
|
||||||
}
|
}
|
||||||
|
|
||||||
var verImpl gomatrixserverlib.IRoomVersion
|
var verImpl gomatrixserverlib.IRoomVersion
|
||||||
|
|
|
@ -43,13 +43,10 @@ func createEventDB() *getEventDB {
|
||||||
|
|
||||||
// Adds a fake event to the storage with given auth events.
|
// Adds a fake event to the storage with given auth events.
|
||||||
func (db *getEventDB) addFakeEvent(eventID string, authIDs []string) error {
|
func (db *getEventDB) addFakeEvent(eventID string, authIDs []string) error {
|
||||||
authEvents := []gomatrixserverlib.EventReference{}
|
authEvents := make([]any, 0, len(authIDs))
|
||||||
for _, authID := range authIDs {
|
for _, authID := range authIDs {
|
||||||
authEvents = append(authEvents, gomatrixserverlib.EventReference{
|
authEvents = append(authEvents, []any{authID, struct{}{}})
|
||||||
EventID: authID,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
builder := map[string]interface{}{
|
builder := map[string]interface{}{
|
||||||
"event_id": eventID,
|
"event_id": eventID,
|
||||||
"auth_events": authEvents,
|
"auth_events": authEvents,
|
||||||
|
|
|
@ -102,7 +102,7 @@ type Database interface {
|
||||||
// Look up event references for the latest events in the room and the current state snapshot.
|
// 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.
|
// Returns the latest events, the current state and the maximum depth of the latest events plus 1.
|
||||||
// Returns an error if there was a problem talking to the database.
|
// Returns an error if there was a problem talking to the database.
|
||||||
LatestEventIDs(ctx context.Context, roomNID types.RoomNID) ([]gomatrixserverlib.EventReference, types.StateSnapshotNID, int64, error)
|
LatestEventIDs(ctx context.Context, roomNID types.RoomNID) ([]string, types.StateSnapshotNID, int64, error)
|
||||||
// Look up the active invites targeting a user in a room and return the
|
// Look up the active invites targeting a user in a room and return the
|
||||||
// numeric state key IDs for the user IDs who sent them along with the event IDs for the invites.
|
// numeric state key IDs for the user IDs who sent them along with the event IDs for the invites.
|
||||||
// Returns an error if there was a problem talking to the database.
|
// Returns an error if there was a problem talking to the database.
|
||||||
|
@ -206,7 +206,7 @@ type RoomDatabase interface {
|
||||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
BulkSelectSnapshotsFromEventIDs(ctx context.Context, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||||
StateEntriesForTuples(ctx context.Context, stateBlockNIDs []types.StateBlockNID, stateKeyTuples []types.StateKeyTuple) ([]types.StateEntryList, error)
|
StateEntriesForTuples(ctx context.Context, stateBlockNIDs []types.StateBlockNID, stateKeyTuples []types.StateKeyTuple) ([]types.StateEntryList, error)
|
||||||
AddState(ctx context.Context, roomNID types.RoomNID, stateBlockNIDs []types.StateBlockNID, state []types.StateEntry) (types.StateSnapshotNID, error)
|
AddState(ctx context.Context, roomNID types.RoomNID, stateBlockNIDs []types.StateBlockNID, state []types.StateEntry) (types.StateSnapshotNID, error)
|
||||||
LatestEventIDs(ctx context.Context, roomNID types.RoomNID) ([]gomatrixserverlib.EventReference, types.StateSnapshotNID, int64, error)
|
LatestEventIDs(ctx context.Context, roomNID types.RoomNID) ([]string, types.StateSnapshotNID, int64, error)
|
||||||
GetOrCreateRoomInfo(ctx context.Context, event gomatrixserverlib.PDU) (*types.RoomInfo, error)
|
GetOrCreateRoomInfo(ctx context.Context, event gomatrixserverlib.PDU) (*types.RoomInfo, error)
|
||||||
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
|
GetOrCreateEventTypeNID(ctx context.Context, eventType string) (eventTypeNID types.EventTypeNID, err error)
|
||||||
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
|
GetOrCreateEventStateKeyNID(ctx context.Context, eventStateKey *string) (types.EventStateKeyNID, error)
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package deltas
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UpDropEventReferenceSHAEvents(ctx context.Context, tx *sql.Tx) error {
|
||||||
|
var count int
|
||||||
|
err := tx.QueryRowContext(ctx, `SELECT count(*) FROM roomserver_events GROUP BY event_id HAVING count(event_id) > 1`).
|
||||||
|
Scan(&count)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return fmt.Errorf("failed to query duplicate event ids")
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
return fmt.Errorf("unable to drop column, as there are duplicate event ids")
|
||||||
|
}
|
||||||
|
_, err = tx.ExecContext(ctx, `ALTER TABLE roomserver_events DROP COLUMN IF EXISTS reference_sha256;`)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpDropEventReferenceSHAPrevEvents(ctx context.Context, tx *sql.Tx) error {
|
||||||
|
_, err := tx.ExecContext(ctx, "ALTER TABLE roomserver_previous_events DROP CONSTRAINT roomserver_previous_event_id_unique;")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||||
|
}
|
||||||
|
_, err = tx.ExecContext(ctx, `ALTER TABLE roomserver_previous_events DROP COLUMN IF EXISTS previous_reference_sha256;`)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||||
|
}
|
||||||
|
_, err = tx.ExecContext(ctx, `ALTER TABLE roomserver_previous_events ADD CONSTRAINT roomserver_previous_event_id_unique UNIQUE (previous_event_id);`)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -22,10 +22,9 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/storage/postgres/deltas"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
)
|
)
|
||||||
|
@ -62,9 +61,6 @@ CREATE TABLE IF NOT EXISTS roomserver_events (
|
||||||
-- Needed for state resolution.
|
-- Needed for state resolution.
|
||||||
-- An event may only appear in this table once.
|
-- An event may only appear in this table once.
|
||||||
event_id TEXT NOT NULL CONSTRAINT roomserver_event_id_unique UNIQUE,
|
event_id TEXT NOT NULL CONSTRAINT roomserver_event_id_unique UNIQUE,
|
||||||
-- The sha256 reference hash for the event.
|
|
||||||
-- Needed for setting reference hashes when sending new events.
|
|
||||||
reference_sha256 BYTEA NOT NULL,
|
|
||||||
-- A list of numeric IDs for events that can authenticate this event.
|
-- A list of numeric IDs for events that can authenticate this event.
|
||||||
auth_event_nids BIGINT[] NOT NULL,
|
auth_event_nids BIGINT[] NOT NULL,
|
||||||
is_rejected BOOLEAN NOT NULL DEFAULT FALSE
|
is_rejected BOOLEAN NOT NULL DEFAULT FALSE
|
||||||
|
@ -75,10 +71,10 @@ CREATE INDEX IF NOT EXISTS roomserver_events_memberships_idx ON roomserver_event
|
||||||
`
|
`
|
||||||
|
|
||||||
const insertEventSQL = "" +
|
const insertEventSQL = "" +
|
||||||
"INSERT INTO roomserver_events AS e (room_nid, event_type_nid, event_state_key_nid, event_id, reference_sha256, auth_event_nids, depth, is_rejected)" +
|
"INSERT INTO roomserver_events AS e (room_nid, event_type_nid, event_state_key_nid, event_id, auth_event_nids, depth, is_rejected)" +
|
||||||
" VALUES ($1, $2, $3, $4, $5, $6, $7, $8)" +
|
" VALUES ($1, $2, $3, $4, $5, $6, $7)" +
|
||||||
" ON CONFLICT ON CONSTRAINT roomserver_event_id_unique DO UPDATE" +
|
" ON CONFLICT ON CONSTRAINT roomserver_event_id_unique DO UPDATE" +
|
||||||
" SET is_rejected = $8 WHERE e.event_id = $4 AND e.is_rejected = TRUE" +
|
" SET is_rejected = $7 WHERE e.event_id = $4 AND e.is_rejected = TRUE" +
|
||||||
" RETURNING event_nid, state_snapshot_nid"
|
" RETURNING event_nid, state_snapshot_nid"
|
||||||
|
|
||||||
const selectEventSQL = "" +
|
const selectEventSQL = "" +
|
||||||
|
@ -130,12 +126,9 @@ const selectEventIDSQL = "" +
|
||||||
"SELECT event_id FROM roomserver_events WHERE event_nid = $1"
|
"SELECT event_id FROM roomserver_events WHERE event_nid = $1"
|
||||||
|
|
||||||
const bulkSelectStateAtEventAndReferenceSQL = "" +
|
const bulkSelectStateAtEventAndReferenceSQL = "" +
|
||||||
"SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid, event_id, reference_sha256" +
|
"SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid, event_id" +
|
||||||
" FROM roomserver_events WHERE event_nid = ANY($1)"
|
" FROM roomserver_events WHERE event_nid = ANY($1)"
|
||||||
|
|
||||||
const bulkSelectEventReferenceSQL = "" +
|
|
||||||
"SELECT event_id, reference_sha256 FROM roomserver_events WHERE event_nid = ANY($1)"
|
|
||||||
|
|
||||||
const bulkSelectEventIDSQL = "" +
|
const bulkSelectEventIDSQL = "" +
|
||||||
"SELECT event_nid, event_id FROM roomserver_events WHERE event_nid = ANY($1)"
|
"SELECT event_nid, event_id FROM roomserver_events WHERE event_nid = ANY($1)"
|
||||||
|
|
||||||
|
@ -167,7 +160,6 @@ type eventStatements struct {
|
||||||
updateEventSentToOutputStmt *sql.Stmt
|
updateEventSentToOutputStmt *sql.Stmt
|
||||||
selectEventIDStmt *sql.Stmt
|
selectEventIDStmt *sql.Stmt
|
||||||
bulkSelectStateAtEventAndReferenceStmt *sql.Stmt
|
bulkSelectStateAtEventAndReferenceStmt *sql.Stmt
|
||||||
bulkSelectEventReferenceStmt *sql.Stmt
|
|
||||||
bulkSelectEventIDStmt *sql.Stmt
|
bulkSelectEventIDStmt *sql.Stmt
|
||||||
bulkSelectEventNIDStmt *sql.Stmt
|
bulkSelectEventNIDStmt *sql.Stmt
|
||||||
bulkSelectUnsentEventNIDStmt *sql.Stmt
|
bulkSelectUnsentEventNIDStmt *sql.Stmt
|
||||||
|
@ -178,7 +170,18 @@ type eventStatements struct {
|
||||||
|
|
||||||
func CreateEventsTable(db *sql.DB) error {
|
func CreateEventsTable(db *sql.DB) error {
|
||||||
_, err := db.Exec(eventsSchema)
|
_, err := db.Exec(eventsSchema)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := sqlutil.NewMigrator(db)
|
||||||
|
m.AddMigrations([]sqlutil.Migration{
|
||||||
|
{
|
||||||
|
Version: "roomserver: drop column reference_sha from roomserver_events",
|
||||||
|
Up: deltas.UpDropEventReferenceSHAEvents,
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
return m.Up(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
||||||
|
@ -197,7 +200,6 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
||||||
{&s.selectEventSentToOutputStmt, selectEventSentToOutputSQL},
|
{&s.selectEventSentToOutputStmt, selectEventSentToOutputSQL},
|
||||||
{&s.selectEventIDStmt, selectEventIDSQL},
|
{&s.selectEventIDStmt, selectEventIDSQL},
|
||||||
{&s.bulkSelectStateAtEventAndReferenceStmt, bulkSelectStateAtEventAndReferenceSQL},
|
{&s.bulkSelectStateAtEventAndReferenceStmt, bulkSelectStateAtEventAndReferenceSQL},
|
||||||
{&s.bulkSelectEventReferenceStmt, bulkSelectEventReferenceSQL},
|
|
||||||
{&s.bulkSelectEventIDStmt, bulkSelectEventIDSQL},
|
{&s.bulkSelectEventIDStmt, bulkSelectEventIDSQL},
|
||||||
{&s.bulkSelectEventNIDStmt, bulkSelectEventNIDSQL},
|
{&s.bulkSelectEventNIDStmt, bulkSelectEventNIDSQL},
|
||||||
{&s.bulkSelectUnsentEventNIDStmt, bulkSelectUnsentEventNIDSQL},
|
{&s.bulkSelectUnsentEventNIDStmt, bulkSelectUnsentEventNIDSQL},
|
||||||
|
@ -214,7 +216,6 @@ func (s *eventStatements) InsertEvent(
|
||||||
eventTypeNID types.EventTypeNID,
|
eventTypeNID types.EventTypeNID,
|
||||||
eventStateKeyNID types.EventStateKeyNID,
|
eventStateKeyNID types.EventStateKeyNID,
|
||||||
eventID string,
|
eventID string,
|
||||||
referenceSHA256 []byte,
|
|
||||||
authEventNIDs []types.EventNID,
|
authEventNIDs []types.EventNID,
|
||||||
depth int64,
|
depth int64,
|
||||||
isRejected bool,
|
isRejected bool,
|
||||||
|
@ -224,7 +225,7 @@ func (s *eventStatements) InsertEvent(
|
||||||
stmt := sqlutil.TxStmt(txn, s.insertEventStmt)
|
stmt := sqlutil.TxStmt(txn, s.insertEventStmt)
|
||||||
err := stmt.QueryRowContext(
|
err := stmt.QueryRowContext(
|
||||||
ctx, int64(roomNID), int64(eventTypeNID), int64(eventStateKeyNID),
|
ctx, int64(roomNID), int64(eventTypeNID), int64(eventStateKeyNID),
|
||||||
eventID, referenceSHA256, eventNIDsAsArray(authEventNIDs), depth,
|
eventID, eventNIDsAsArray(authEventNIDs), depth,
|
||||||
isRejected,
|
isRejected,
|
||||||
).Scan(&eventNID, &stateNID)
|
).Scan(&eventNID, &stateNID)
|
||||||
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
||||||
|
@ -441,11 +442,10 @@ func (s *eventStatements) BulkSelectStateAtEventAndReference(
|
||||||
eventNID int64
|
eventNID int64
|
||||||
stateSnapshotNID int64
|
stateSnapshotNID int64
|
||||||
eventID string
|
eventID string
|
||||||
eventSHA256 []byte
|
|
||||||
)
|
)
|
||||||
for ; rows.Next(); i++ {
|
for ; rows.Next(); i++ {
|
||||||
if err = rows.Scan(
|
if err = rows.Scan(
|
||||||
&eventTypeNID, &eventStateKeyNID, &eventNID, &stateSnapshotNID, &eventID, &eventSHA256,
|
&eventTypeNID, &eventStateKeyNID, &eventNID, &stateSnapshotNID, &eventID,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -455,32 +455,6 @@ func (s *eventStatements) BulkSelectStateAtEventAndReference(
|
||||||
result.EventNID = types.EventNID(eventNID)
|
result.EventNID = types.EventNID(eventNID)
|
||||||
result.BeforeStateSnapshotNID = types.StateSnapshotNID(stateSnapshotNID)
|
result.BeforeStateSnapshotNID = types.StateSnapshotNID(stateSnapshotNID)
|
||||||
result.EventID = eventID
|
result.EventID = eventID
|
||||||
result.EventSHA256 = eventSHA256
|
|
||||||
}
|
|
||||||
if err = rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if i != len(eventNIDs) {
|
|
||||||
return nil, fmt.Errorf("storage: event NIDs missing from the database (%d != %d)", i, len(eventNIDs))
|
|
||||||
}
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *eventStatements) BulkSelectEventReference(
|
|
||||||
ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID,
|
|
||||||
) ([]gomatrixserverlib.EventReference, error) {
|
|
||||||
rows, err := s.bulkSelectEventReferenceStmt.QueryContext(ctx, eventNIDsAsArray(eventNIDs))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer internal.CloseAndLogIfError(ctx, rows, "bulkSelectEventReference: rows.close() failed")
|
|
||||||
results := make([]gomatrixserverlib.EventReference, len(eventNIDs))
|
|
||||||
i := 0
|
|
||||||
for ; rows.Next(); i++ {
|
|
||||||
result := &results[i]
|
|
||||||
if err = rows.Scan(&result.EventID, &result.EventSHA256); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err = rows.Err(); err != nil {
|
if err = rows.Err(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/storage/postgres/deltas"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
)
|
)
|
||||||
|
@ -32,11 +33,9 @@ const previousEventSchema = `
|
||||||
CREATE TABLE IF NOT EXISTS roomserver_previous_events (
|
CREATE TABLE IF NOT EXISTS roomserver_previous_events (
|
||||||
-- The string event ID taken from the prev_events key of an event.
|
-- The string event ID taken from the prev_events key of an event.
|
||||||
previous_event_id TEXT NOT NULL,
|
previous_event_id TEXT NOT NULL,
|
||||||
-- The SHA256 reference hash taken from the prev_events key of an event.
|
|
||||||
previous_reference_sha256 BYTEA NOT NULL,
|
|
||||||
-- A list of numeric event IDs of events that reference this prev_event.
|
-- A list of numeric event IDs of events that reference this prev_event.
|
||||||
event_nids BIGINT[] NOT NULL,
|
event_nids BIGINT[] NOT NULL,
|
||||||
CONSTRAINT roomserver_previous_event_id_unique UNIQUE (previous_event_id, previous_reference_sha256)
|
CONSTRAINT roomserver_previous_event_id_unique UNIQUE (previous_event_id)
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -47,17 +46,17 @@ CREATE TABLE IF NOT EXISTS roomserver_previous_events (
|
||||||
// The lock is necessary to avoid data races when checking whether an event is already referenced by another event.
|
// The lock is necessary to avoid data races when checking whether an event is already referenced by another event.
|
||||||
const insertPreviousEventSQL = "" +
|
const insertPreviousEventSQL = "" +
|
||||||
"INSERT INTO roomserver_previous_events" +
|
"INSERT INTO roomserver_previous_events" +
|
||||||
" (previous_event_id, previous_reference_sha256, event_nids)" +
|
" (previous_event_id, event_nids)" +
|
||||||
" VALUES ($1, $2, array_append('{}'::bigint[], $3))" +
|
" VALUES ($1, array_append('{}'::bigint[], $2))" +
|
||||||
" ON CONFLICT ON CONSTRAINT roomserver_previous_event_id_unique" +
|
" ON CONFLICT ON CONSTRAINT roomserver_previous_event_id_unique" +
|
||||||
" DO UPDATE SET event_nids = array_append(roomserver_previous_events.event_nids, $3)" +
|
" DO UPDATE SET event_nids = array_append(roomserver_previous_events.event_nids, $2)" +
|
||||||
" WHERE $3 != ALL(roomserver_previous_events.event_nids)"
|
" WHERE $2 != ALL(roomserver_previous_events.event_nids)"
|
||||||
|
|
||||||
// Check if the event is referenced by another event in the table.
|
// Check if the event is referenced by another event in the table.
|
||||||
// This should only be done while holding a "FOR UPDATE" lock on the row in the rooms table for this room.
|
// This should only be done while holding a "FOR UPDATE" lock on the row in the rooms table for this room.
|
||||||
const selectPreviousEventExistsSQL = "" +
|
const selectPreviousEventExistsSQL = "" +
|
||||||
"SELECT 1 FROM roomserver_previous_events" +
|
"SELECT 1 FROM roomserver_previous_events" +
|
||||||
" WHERE previous_event_id = $1 AND previous_reference_sha256 = $2"
|
" WHERE previous_event_id = $1"
|
||||||
|
|
||||||
type previousEventStatements struct {
|
type previousEventStatements struct {
|
||||||
insertPreviousEventStmt *sql.Stmt
|
insertPreviousEventStmt *sql.Stmt
|
||||||
|
@ -66,7 +65,18 @@ type previousEventStatements struct {
|
||||||
|
|
||||||
func CreatePrevEventsTable(db *sql.DB) error {
|
func CreatePrevEventsTable(db *sql.DB) error {
|
||||||
_, err := db.Exec(previousEventSchema)
|
_, err := db.Exec(previousEventSchema)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := sqlutil.NewMigrator(db)
|
||||||
|
m.AddMigrations([]sqlutil.Migration{
|
||||||
|
{
|
||||||
|
Version: "roomserver: drop column reference_sha from roomserver_prev_events",
|
||||||
|
Up: deltas.UpDropEventReferenceSHAPrevEvents,
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
return m.Up(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
func PreparePrevEventsTable(db *sql.DB) (tables.PreviousEvents, error) {
|
func PreparePrevEventsTable(db *sql.DB) (tables.PreviousEvents, error) {
|
||||||
|
@ -82,12 +92,11 @@ func (s *previousEventStatements) InsertPreviousEvent(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
txn *sql.Tx,
|
txn *sql.Tx,
|
||||||
previousEventID string,
|
previousEventID string,
|
||||||
previousEventReferenceSHA256 []byte,
|
|
||||||
eventNID types.EventNID,
|
eventNID types.EventNID,
|
||||||
) error {
|
) error {
|
||||||
stmt := sqlutil.TxStmt(txn, s.insertPreviousEventStmt)
|
stmt := sqlutil.TxStmt(txn, s.insertPreviousEventStmt)
|
||||||
_, err := stmt.ExecContext(
|
_, err := stmt.ExecContext(
|
||||||
ctx, previousEventID, previousEventReferenceSHA256, int64(eventNID),
|
ctx, previousEventID, int64(eventNID),
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -95,9 +104,9 @@ func (s *previousEventStatements) InsertPreviousEvent(
|
||||||
// Check if the event reference exists
|
// Check if the event reference exists
|
||||||
// Returns sql.ErrNoRows if the event reference doesn't exist.
|
// Returns sql.ErrNoRows if the event reference doesn't exist.
|
||||||
func (s *previousEventStatements) SelectPreviousEventExists(
|
func (s *previousEventStatements) SelectPreviousEventExists(
|
||||||
ctx context.Context, txn *sql.Tx, eventID string, eventReferenceSHA256 []byte,
|
ctx context.Context, txn *sql.Tx, eventID string,
|
||||||
) error {
|
) error {
|
||||||
var ok int64
|
var ok int64
|
||||||
stmt := sqlutil.TxStmt(txn, s.selectPreviousEventExistsStmt)
|
stmt := sqlutil.TxStmt(txn, s.selectPreviousEventExistsStmt)
|
||||||
return stmt.QueryRowContext(ctx, eventID, eventReferenceSHA256).Scan(&ok)
|
return stmt.QueryRowContext(ctx, eventID).Scan(&ok)
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,18 +104,6 @@ func (u *RoomUpdater) CurrentStateSnapshotNID() types.StateSnapshotNID {
|
||||||
return u.currentStateSnapshotNID
|
return u.currentStateSnapshotNID
|
||||||
}
|
}
|
||||||
|
|
||||||
// StorePreviousEvents implements types.RoomRecentEventsUpdater - This must be called from a Writer
|
|
||||||
func (u *RoomUpdater) StorePreviousEvents(eventNID types.EventNID, previousEventReferences []gomatrixserverlib.EventReference) error {
|
|
||||||
return u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error {
|
|
||||||
for _, ref := range previousEventReferences {
|
|
||||||
if err := u.d.PrevEventsTable.InsertPreviousEvent(u.ctx, txn, ref.EventID, ref.EventSHA256, eventNID); err != nil {
|
|
||||||
return fmt.Errorf("u.d.PrevEventsTable.InsertPreviousEvent: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *RoomUpdater) Events(ctx context.Context, _ gomatrixserverlib.RoomVersion, eventNIDs []types.EventNID) ([]types.Event, error) {
|
func (u *RoomUpdater) Events(ctx context.Context, _ gomatrixserverlib.RoomVersion, eventNIDs []types.EventNID) ([]types.Event, error) {
|
||||||
if u.roomInfo == nil {
|
if u.roomInfo == nil {
|
||||||
return nil, types.ErrorInvalidRoomInfo
|
return nil, types.ErrorInvalidRoomInfo
|
||||||
|
@ -203,8 +191,8 @@ func (u *RoomUpdater) EventsFromIDs(ctx context.Context, roomInfo *types.RoomInf
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsReferenced implements types.RoomRecentEventsUpdater
|
// IsReferenced implements types.RoomRecentEventsUpdater
|
||||||
func (u *RoomUpdater) IsReferenced(eventReference gomatrixserverlib.EventReference) (bool, error) {
|
func (u *RoomUpdater) IsReferenced(eventID string) (bool, error) {
|
||||||
err := u.d.PrevEventsTable.SelectPreviousEventExists(u.ctx, u.txn, eventReference.EventID, eventReference.EventSHA256)
|
err := u.d.PrevEventsTable.SelectPreviousEventExists(u.ctx, u.txn, eventID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,15 +398,13 @@ func (d *EventDatabase) eventsFromIDs(ctx context.Context, txn *sql.Tx, roomInfo
|
||||||
return d.events(ctx, txn, roomInfo.RoomVersion, nids)
|
return d.events(ctx, txn, roomInfo.RoomVersion, nids)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Database) LatestEventIDs(
|
func (d *Database) LatestEventIDs(ctx context.Context, roomNID types.RoomNID) (references []string, currentStateSnapshotNID types.StateSnapshotNID, depth int64, err error) {
|
||||||
ctx context.Context, roomNID types.RoomNID,
|
|
||||||
) (references []gomatrixserverlib.EventReference, currentStateSnapshotNID types.StateSnapshotNID, depth int64, err error) {
|
|
||||||
var eventNIDs []types.EventNID
|
var eventNIDs []types.EventNID
|
||||||
eventNIDs, currentStateSnapshotNID, err = d.RoomsTable.SelectLatestEventNIDs(ctx, nil, roomNID)
|
eventNIDs, currentStateSnapshotNID, err = d.RoomsTable.SelectLatestEventNIDs(ctx, nil, roomNID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
references, err = d.EventsTable.BulkSelectEventReference(ctx, nil, eventNIDs)
|
eventNIDMap, err := d.EventsTable.BulkSelectEventID(ctx, nil, eventNIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -414,6 +412,9 @@ func (d *Database) LatestEventIDs(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
for _, eventID := range eventNIDMap {
|
||||||
|
references = append(references, eventID)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +743,6 @@ func (d *EventDatabase) StoreEvent(
|
||||||
eventTypeNID,
|
eventTypeNID,
|
||||||
eventStateKeyNID,
|
eventStateKeyNID,
|
||||||
event.EventID(),
|
event.EventID(),
|
||||||
event.EventReference().EventSHA256,
|
|
||||||
authEventNIDs,
|
authEventNIDs,
|
||||||
event.Depth(),
|
event.Depth(),
|
||||||
isRejected,
|
isRejected,
|
||||||
|
@ -762,7 +762,7 @@ func (d *EventDatabase) StoreEvent(
|
||||||
return fmt.Errorf("d.EventJSONTable.InsertEventJSON: %w", err)
|
return fmt.Errorf("d.EventJSONTable.InsertEventJSON: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevEvents := event.PrevEvents(); len(prevEvents) > 0 {
|
if prevEvents := event.PrevEventIDs(); len(prevEvents) > 0 {
|
||||||
// Create an updater - NB: on sqlite this WILL create a txn as we are directly calling the shared DB form of
|
// Create an updater - NB: on sqlite this WILL create a txn as we are directly calling the shared DB form of
|
||||||
// GetLatestEventsForUpdate - not via the SQLiteDatabase form which has `nil` txns. This
|
// GetLatestEventsForUpdate - not via the SQLiteDatabase form which has `nil` txns. This
|
||||||
// function only does SELECTs though so the created txn (at this point) is just a read txn like
|
// function only does SELECTs though so the created txn (at this point) is just a read txn like
|
||||||
|
@ -770,8 +770,8 @@ func (d *EventDatabase) StoreEvent(
|
||||||
// to do writes however then this will need to go inside `Writer.Do`.
|
// to do writes however then this will need to go inside `Writer.Do`.
|
||||||
|
|
||||||
// The following is a copy of RoomUpdater.StorePreviousEvents
|
// The following is a copy of RoomUpdater.StorePreviousEvents
|
||||||
for _, ref := range prevEvents {
|
for _, eventID := range prevEvents {
|
||||||
if err = d.PrevEventsTable.InsertPreviousEvent(ctx, txn, ref.EventID, ref.EventSHA256, eventNID); err != nil {
|
if err = d.PrevEventsTable.InsertPreviousEvent(ctx, txn, eventID, eventNID); err != nil {
|
||||||
return fmt.Errorf("u.d.PrevEventsTable.InsertPreviousEvent: %w", err)
|
return fmt.Errorf("u.d.PrevEventsTable.InsertPreviousEvent: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package deltas
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UpDropEventReferenceSHA(ctx context.Context, tx *sql.Tx) error {
|
||||||
|
var count int
|
||||||
|
err := tx.QueryRowContext(ctx, `SELECT count(*) FROM roomserver_events GROUP BY event_id HAVING count(event_id) > 1`).
|
||||||
|
Scan(&count)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
return fmt.Errorf("failed to query duplicate event ids")
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
return fmt.Errorf("unable to drop column, as there are duplicate event ids")
|
||||||
|
}
|
||||||
|
_, err = tx.ExecContext(ctx, `ALTER TABLE roomserver_events DROP COLUMN reference_sha256;`)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpDropEventReferenceSHAPrevEvents(ctx context.Context, tx *sql.Tx) error {
|
||||||
|
// rename the table
|
||||||
|
if _, err := tx.ExecContext(ctx, `ALTER TABLE roomserver_previous_events RENAME TO _roomserver_previous_events;`); err != nil {
|
||||||
|
return fmt.Errorf("tx.ExecContext: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new table
|
||||||
|
if _, err := tx.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS roomserver_previous_events (
|
||||||
|
previous_event_id TEXT NOT NULL,
|
||||||
|
event_nids TEXT NOT NULL,
|
||||||
|
UNIQUE (previous_event_id)
|
||||||
|
);`); err != nil {
|
||||||
|
return fmt.Errorf("tx.ExecContext: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// move data
|
||||||
|
if _, err := tx.ExecContext(ctx, `
|
||||||
|
INSERT
|
||||||
|
INTO roomserver_previous_events (
|
||||||
|
previous_event_id, event_nids
|
||||||
|
) SELECT
|
||||||
|
previous_event_id, event_nids
|
||||||
|
FROM _roomserver_previous_events
|
||||||
|
;`); err != nil {
|
||||||
|
return fmt.Errorf("tx.ExecContext: %w", err)
|
||||||
|
}
|
||||||
|
// drop old table
|
||||||
|
_, err := tx.ExecContext(ctx, `DROP TABLE _roomserver_previous_events;`)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to execute upgrade: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -19,14 +19,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal"
|
"github.com/matrix-org/dendrite/internal"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/storage/sqlite3/deltas"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
)
|
)
|
||||||
|
@ -41,17 +41,16 @@ const eventsSchema = `
|
||||||
state_snapshot_nid INTEGER NOT NULL DEFAULT 0,
|
state_snapshot_nid INTEGER NOT NULL DEFAULT 0,
|
||||||
depth INTEGER NOT NULL,
|
depth INTEGER NOT NULL,
|
||||||
event_id TEXT NOT NULL UNIQUE,
|
event_id TEXT NOT NULL UNIQUE,
|
||||||
reference_sha256 BLOB NOT NULL,
|
|
||||||
auth_event_nids TEXT NOT NULL DEFAULT '[]',
|
auth_event_nids TEXT NOT NULL DEFAULT '[]',
|
||||||
is_rejected BOOLEAN NOT NULL DEFAULT FALSE
|
is_rejected BOOLEAN NOT NULL DEFAULT FALSE
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
|
|
||||||
const insertEventSQL = `
|
const insertEventSQL = `
|
||||||
INSERT INTO roomserver_events (room_nid, event_type_nid, event_state_key_nid, event_id, reference_sha256, auth_event_nids, depth, is_rejected)
|
INSERT INTO roomserver_events (room_nid, event_type_nid, event_state_key_nid, event_id, auth_event_nids, depth, is_rejected)
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
ON CONFLICT DO UPDATE
|
ON CONFLICT DO UPDATE
|
||||||
SET is_rejected = $8 WHERE is_rejected = 1
|
SET is_rejected = $7 WHERE is_rejected = 1
|
||||||
RETURNING event_nid, state_snapshot_nid;
|
RETURNING event_nid, state_snapshot_nid;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -100,12 +99,9 @@ const selectEventIDSQL = "" +
|
||||||
"SELECT event_id FROM roomserver_events WHERE event_nid = $1"
|
"SELECT event_id FROM roomserver_events WHERE event_nid = $1"
|
||||||
|
|
||||||
const bulkSelectStateAtEventAndReferenceSQL = "" +
|
const bulkSelectStateAtEventAndReferenceSQL = "" +
|
||||||
"SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid, event_id, reference_sha256" +
|
"SELECT event_type_nid, event_state_key_nid, event_nid, state_snapshot_nid, event_id" +
|
||||||
" FROM roomserver_events WHERE event_nid IN ($1)"
|
" FROM roomserver_events WHERE event_nid IN ($1)"
|
||||||
|
|
||||||
const bulkSelectEventReferenceSQL = "" +
|
|
||||||
"SELECT event_id, reference_sha256 FROM roomserver_events WHERE event_nid IN ($1)"
|
|
||||||
|
|
||||||
const bulkSelectEventIDSQL = "" +
|
const bulkSelectEventIDSQL = "" +
|
||||||
"SELECT event_nid, event_id FROM roomserver_events WHERE event_nid IN ($1)"
|
"SELECT event_nid, event_id FROM roomserver_events WHERE event_nid IN ($1)"
|
||||||
|
|
||||||
|
@ -137,7 +133,6 @@ type eventStatements struct {
|
||||||
updateEventSentToOutputStmt *sql.Stmt
|
updateEventSentToOutputStmt *sql.Stmt
|
||||||
selectEventIDStmt *sql.Stmt
|
selectEventIDStmt *sql.Stmt
|
||||||
bulkSelectStateAtEventAndReferenceStmt *sql.Stmt
|
bulkSelectStateAtEventAndReferenceStmt *sql.Stmt
|
||||||
bulkSelectEventReferenceStmt *sql.Stmt
|
|
||||||
bulkSelectEventIDStmt *sql.Stmt
|
bulkSelectEventIDStmt *sql.Stmt
|
||||||
selectEventRejectedStmt *sql.Stmt
|
selectEventRejectedStmt *sql.Stmt
|
||||||
//bulkSelectEventNIDStmt *sql.Stmt
|
//bulkSelectEventNIDStmt *sql.Stmt
|
||||||
|
@ -147,7 +142,32 @@ type eventStatements struct {
|
||||||
|
|
||||||
func CreateEventsTable(db *sql.DB) error {
|
func CreateEventsTable(db *sql.DB) error {
|
||||||
_, err := db.Exec(eventsSchema)
|
_, err := db.Exec(eventsSchema)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the column exists
|
||||||
|
var cName string
|
||||||
|
migrationName := "roomserver: drop column reference_sha from roomserver_events"
|
||||||
|
err = db.QueryRowContext(context.Background(), `SELECT p.name FROM sqlite_master AS m JOIN pragma_table_info(m.name) AS p WHERE m.name = 'roomserver_events' AND p.name = 'reference_sha256'`).Scan(&cName)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) { // migration was already executed, as the column was removed
|
||||||
|
if err = sqlutil.InsertMigration(context.Background(), db, migrationName); err != nil {
|
||||||
|
return fmt.Errorf("unable to manually insert migration '%s': %w", migrationName, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := sqlutil.NewMigrator(db)
|
||||||
|
m.AddMigrations([]sqlutil.Migration{
|
||||||
|
{
|
||||||
|
Version: migrationName,
|
||||||
|
Up: deltas.UpDropEventReferenceSHA,
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
return m.Up(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
||||||
|
@ -167,7 +187,6 @@ func PrepareEventsTable(db *sql.DB) (tables.Events, error) {
|
||||||
{&s.selectEventSentToOutputStmt, selectEventSentToOutputSQL},
|
{&s.selectEventSentToOutputStmt, selectEventSentToOutputSQL},
|
||||||
{&s.selectEventIDStmt, selectEventIDSQL},
|
{&s.selectEventIDStmt, selectEventIDSQL},
|
||||||
{&s.bulkSelectStateAtEventAndReferenceStmt, bulkSelectStateAtEventAndReferenceSQL},
|
{&s.bulkSelectStateAtEventAndReferenceStmt, bulkSelectStateAtEventAndReferenceSQL},
|
||||||
{&s.bulkSelectEventReferenceStmt, bulkSelectEventReferenceSQL},
|
|
||||||
{&s.bulkSelectEventIDStmt, bulkSelectEventIDSQL},
|
{&s.bulkSelectEventIDStmt, bulkSelectEventIDSQL},
|
||||||
//{&s.bulkSelectEventNIDStmt, bulkSelectEventNIDSQL},
|
//{&s.bulkSelectEventNIDStmt, bulkSelectEventNIDSQL},
|
||||||
//{&s.bulkSelectUnsentEventNIDStmt, bulkSelectUnsentEventNIDSQL},
|
//{&s.bulkSelectUnsentEventNIDStmt, bulkSelectUnsentEventNIDSQL},
|
||||||
|
@ -183,7 +202,6 @@ func (s *eventStatements) InsertEvent(
|
||||||
eventTypeNID types.EventTypeNID,
|
eventTypeNID types.EventTypeNID,
|
||||||
eventStateKeyNID types.EventStateKeyNID,
|
eventStateKeyNID types.EventStateKeyNID,
|
||||||
eventID string,
|
eventID string,
|
||||||
referenceSHA256 []byte,
|
|
||||||
authEventNIDs []types.EventNID,
|
authEventNIDs []types.EventNID,
|
||||||
depth int64,
|
depth int64,
|
||||||
isRejected bool,
|
isRejected bool,
|
||||||
|
@ -194,7 +212,7 @@ func (s *eventStatements) InsertEvent(
|
||||||
insertStmt := sqlutil.TxStmt(txn, s.insertEventStmt)
|
insertStmt := sqlutil.TxStmt(txn, s.insertEventStmt)
|
||||||
err := insertStmt.QueryRowContext(
|
err := insertStmt.QueryRowContext(
|
||||||
ctx, int64(roomNID), int64(eventTypeNID), int64(eventStateKeyNID),
|
ctx, int64(roomNID), int64(eventTypeNID), int64(eventStateKeyNID),
|
||||||
eventID, referenceSHA256, eventNIDsAsArray(authEventNIDs), depth, isRejected,
|
eventID, eventNIDsAsArray(authEventNIDs), depth, isRejected,
|
||||||
).Scan(&eventNID, &stateNID)
|
).Scan(&eventNID, &stateNID)
|
||||||
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
return types.EventNID(eventNID), types.StateSnapshotNID(stateNID), err
|
||||||
}
|
}
|
||||||
|
@ -475,11 +493,10 @@ func (s *eventStatements) BulkSelectStateAtEventAndReference(
|
||||||
eventNID int64
|
eventNID int64
|
||||||
stateSnapshotNID int64
|
stateSnapshotNID int64
|
||||||
eventID string
|
eventID string
|
||||||
eventSHA256 []byte
|
|
||||||
)
|
)
|
||||||
for ; rows.Next(); i++ {
|
for ; rows.Next(); i++ {
|
||||||
if err = rows.Scan(
|
if err = rows.Scan(
|
||||||
&eventTypeNID, &eventStateKeyNID, &eventNID, &stateSnapshotNID, &eventID, &eventSHA256,
|
&eventTypeNID, &eventStateKeyNID, &eventNID, &stateSnapshotNID, &eventID,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -489,43 +506,6 @@ func (s *eventStatements) BulkSelectStateAtEventAndReference(
|
||||||
result.EventNID = types.EventNID(eventNID)
|
result.EventNID = types.EventNID(eventNID)
|
||||||
result.BeforeStateSnapshotNID = types.StateSnapshotNID(stateSnapshotNID)
|
result.BeforeStateSnapshotNID = types.StateSnapshotNID(stateSnapshotNID)
|
||||||
result.EventID = eventID
|
result.EventID = eventID
|
||||||
result.EventSHA256 = eventSHA256
|
|
||||||
}
|
|
||||||
if i != len(eventNIDs) {
|
|
||||||
return nil, fmt.Errorf("storage: event NIDs missing from the database (%d != %d)", i, len(eventNIDs))
|
|
||||||
}
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *eventStatements) BulkSelectEventReference(
|
|
||||||
ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID,
|
|
||||||
) ([]gomatrixserverlib.EventReference, error) {
|
|
||||||
///////////////
|
|
||||||
iEventNIDs := make([]interface{}, len(eventNIDs))
|
|
||||||
for k, v := range eventNIDs {
|
|
||||||
iEventNIDs[k] = v
|
|
||||||
}
|
|
||||||
selectOrig := strings.Replace(bulkSelectEventReferenceSQL, "($1)", sqlutil.QueryVariadic(len(iEventNIDs)), 1)
|
|
||||||
selectPrep, err := s.db.Prepare(selectOrig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer selectPrep.Close() // nolint:errcheck
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
selectStmt := sqlutil.TxStmt(txn, selectPrep)
|
|
||||||
rows, err := selectStmt.QueryContext(ctx, iEventNIDs...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer internal.CloseAndLogIfError(ctx, rows, "bulkSelectEventReference: rows.close() failed")
|
|
||||||
results := make([]gomatrixserverlib.EventReference, len(eventNIDs))
|
|
||||||
i := 0
|
|
||||||
for ; rows.Next(); i++ {
|
|
||||||
result := &results[i]
|
|
||||||
if err = rows.Scan(&result.EventID, &result.EventSHA256); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if i != len(eventNIDs) {
|
if i != len(eventNIDs) {
|
||||||
return nil, fmt.Errorf("storage: event NIDs missing from the database (%d != %d)", i, len(eventNIDs))
|
return nil, fmt.Errorf("storage: event NIDs missing from the database (%d != %d)", i, len(eventNIDs))
|
||||||
|
|
|
@ -18,10 +18,12 @@ package sqlite3
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
|
"github.com/matrix-org/dendrite/roomserver/storage/sqlite3/deltas"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
"github.com/matrix-org/dendrite/roomserver/storage/tables"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
)
|
)
|
||||||
|
@ -34,9 +36,8 @@ import (
|
||||||
const previousEventSchema = `
|
const previousEventSchema = `
|
||||||
CREATE TABLE IF NOT EXISTS roomserver_previous_events (
|
CREATE TABLE IF NOT EXISTS roomserver_previous_events (
|
||||||
previous_event_id TEXT NOT NULL,
|
previous_event_id TEXT NOT NULL,
|
||||||
previous_reference_sha256 BLOB,
|
|
||||||
event_nids TEXT NOT NULL,
|
event_nids TEXT NOT NULL,
|
||||||
UNIQUE (previous_event_id, previous_reference_sha256)
|
UNIQUE (previous_event_id)
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -47,20 +48,20 @@ const previousEventSchema = `
|
||||||
// The lock is necessary to avoid data races when checking whether an event is already referenced by another event.
|
// The lock is necessary to avoid data races when checking whether an event is already referenced by another event.
|
||||||
const insertPreviousEventSQL = `
|
const insertPreviousEventSQL = `
|
||||||
INSERT OR REPLACE INTO roomserver_previous_events
|
INSERT OR REPLACE INTO roomserver_previous_events
|
||||||
(previous_event_id, previous_reference_sha256, event_nids)
|
(previous_event_id, event_nids)
|
||||||
VALUES ($1, $2, $3)
|
VALUES ($1, $2)
|
||||||
`
|
`
|
||||||
|
|
||||||
const selectPreviousEventNIDsSQL = `
|
const selectPreviousEventNIDsSQL = `
|
||||||
SELECT event_nids FROM roomserver_previous_events
|
SELECT event_nids FROM roomserver_previous_events
|
||||||
WHERE previous_event_id = $1 AND previous_reference_sha256 = $2
|
WHERE previous_event_id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
// Check if the event is referenced by another event in the table.
|
// Check if the event is referenced by another event in the table.
|
||||||
// This should only be done while holding a "FOR UPDATE" lock on the row in the rooms table for this room.
|
// This should only be done while holding a "FOR UPDATE" lock on the row in the rooms table for this room.
|
||||||
const selectPreviousEventExistsSQL = `
|
const selectPreviousEventExistsSQL = `
|
||||||
SELECT 1 FROM roomserver_previous_events
|
SELECT 1 FROM roomserver_previous_events
|
||||||
WHERE previous_event_id = $1 AND previous_reference_sha256 = $2
|
WHERE previous_event_id = $1
|
||||||
`
|
`
|
||||||
|
|
||||||
type previousEventStatements struct {
|
type previousEventStatements struct {
|
||||||
|
@ -72,7 +73,30 @@ type previousEventStatements struct {
|
||||||
|
|
||||||
func CreatePrevEventsTable(db *sql.DB) error {
|
func CreatePrevEventsTable(db *sql.DB) error {
|
||||||
_, err := db.Exec(previousEventSchema)
|
_, err := db.Exec(previousEventSchema)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// check if the column exists
|
||||||
|
var cName string
|
||||||
|
migrationName := "roomserver: drop column reference_sha from roomserver_prev_events"
|
||||||
|
err = db.QueryRowContext(context.Background(), `SELECT p.name FROM sqlite_master AS m JOIN pragma_table_info(m.name) AS p WHERE m.name = 'roomserver_previous_events' AND p.name = 'previous_reference_sha256'`).Scan(&cName)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) { // migration was already executed, as the column was removed
|
||||||
|
if err = sqlutil.InsertMigration(context.Background(), db, migrationName); err != nil {
|
||||||
|
return fmt.Errorf("unable to manually insert migration '%s': %w", migrationName, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m := sqlutil.NewMigrator(db)
|
||||||
|
m.AddMigrations([]sqlutil.Migration{
|
||||||
|
{
|
||||||
|
Version: migrationName,
|
||||||
|
Up: deltas.UpDropEventReferenceSHAPrevEvents,
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
return m.Up(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
func PreparePrevEventsTable(db *sql.DB) (tables.PreviousEvents, error) {
|
func PreparePrevEventsTable(db *sql.DB) (tables.PreviousEvents, error) {
|
||||||
|
@ -91,13 +115,12 @@ func (s *previousEventStatements) InsertPreviousEvent(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
txn *sql.Tx,
|
txn *sql.Tx,
|
||||||
previousEventID string,
|
previousEventID string,
|
||||||
previousEventReferenceSHA256 []byte,
|
|
||||||
eventNID types.EventNID,
|
eventNID types.EventNID,
|
||||||
) error {
|
) error {
|
||||||
var eventNIDs string
|
var eventNIDs string
|
||||||
eventNIDAsString := fmt.Sprintf("%d", eventNID)
|
eventNIDAsString := fmt.Sprintf("%d", eventNID)
|
||||||
selectStmt := sqlutil.TxStmt(txn, s.selectPreviousEventExistsStmt)
|
selectStmt := sqlutil.TxStmt(txn, s.selectPreviousEventExistsStmt)
|
||||||
err := selectStmt.QueryRowContext(ctx, previousEventID, previousEventReferenceSHA256).Scan(&eventNIDs)
|
err := selectStmt.QueryRowContext(ctx, previousEventID).Scan(&eventNIDs)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return fmt.Errorf("selectStmt.QueryRowContext.Scan: %w", err)
|
return fmt.Errorf("selectStmt.QueryRowContext.Scan: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -115,7 +138,7 @@ func (s *previousEventStatements) InsertPreviousEvent(
|
||||||
}
|
}
|
||||||
insertStmt := sqlutil.TxStmt(txn, s.insertPreviousEventStmt)
|
insertStmt := sqlutil.TxStmt(txn, s.insertPreviousEventStmt)
|
||||||
_, err = insertStmt.ExecContext(
|
_, err = insertStmt.ExecContext(
|
||||||
ctx, previousEventID, previousEventReferenceSHA256, eventNIDs,
|
ctx, previousEventID, eventNIDs,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -123,9 +146,9 @@ func (s *previousEventStatements) InsertPreviousEvent(
|
||||||
// Check if the event reference exists
|
// Check if the event reference exists
|
||||||
// Returns sql.ErrNoRows if the event reference doesn't exist.
|
// Returns sql.ErrNoRows if the event reference doesn't exist.
|
||||||
func (s *previousEventStatements) SelectPreviousEventExists(
|
func (s *previousEventStatements) SelectPreviousEventExists(
|
||||||
ctx context.Context, txn *sql.Tx, eventID string, eventReferenceSHA256 []byte,
|
ctx context.Context, txn *sql.Tx, eventID string,
|
||||||
) error {
|
) error {
|
||||||
var ok int64
|
var ok int64
|
||||||
stmt := sqlutil.TxStmt(txn, s.selectPreviousEventExistsStmt)
|
stmt := sqlutil.TxStmt(txn, s.selectPreviousEventExistsStmt)
|
||||||
return stmt.QueryRowContext(ctx, eventID, eventReferenceSHA256).Scan(&ok)
|
return stmt.QueryRowContext(ctx, eventID).Scan(&ok)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,13 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
|
|
||||||
"github.com/matrix-org/dendrite/internal/caching"
|
"github.com/matrix-org/dendrite/internal/caching"
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil"
|
"github.com/matrix-org/dendrite/internal/sqlutil"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
"github.com/matrix-org/dendrite/roomserver/storage/shared"
|
||||||
"github.com/matrix-org/dendrite/roomserver/storage/sqlite3/deltas"
|
"github.com/matrix-org/dendrite/roomserver/storage/sqlite3/deltas"
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Database is used to store room events and stream offsets.
|
// A Database is used to store room events and stream offsets.
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/matrix-org/dendrite/roomserver/types"
|
"github.com/matrix-org/dendrite/roomserver/types"
|
||||||
"github.com/matrix-org/dendrite/setup/config"
|
"github.com/matrix-org/dendrite/setup/config"
|
||||||
"github.com/matrix-org/dendrite/test"
|
"github.com/matrix-org/dendrite/test"
|
||||||
"github.com/matrix-org/gomatrixserverlib"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,10 +47,9 @@ func Test_EventsTable(t *testing.T) {
|
||||||
// create some dummy data
|
// create some dummy data
|
||||||
eventIDs := make([]string, 0, len(room.Events()))
|
eventIDs := make([]string, 0, len(room.Events()))
|
||||||
wantStateAtEvent := make([]types.StateAtEvent, 0, len(room.Events()))
|
wantStateAtEvent := make([]types.StateAtEvent, 0, len(room.Events()))
|
||||||
wantEventReferences := make([]gomatrixserverlib.EventReference, 0, len(room.Events()))
|
|
||||||
wantStateAtEventAndRefs := make([]types.StateAtEventAndReference, 0, len(room.Events()))
|
wantStateAtEventAndRefs := make([]types.StateAtEventAndReference, 0, len(room.Events()))
|
||||||
for _, ev := range room.Events() {
|
for _, ev := range room.Events() {
|
||||||
eventNID, snapNID, err := tab.InsertEvent(ctx, nil, 1, 1, 1, ev.EventID(), ev.EventReference().EventSHA256, nil, ev.Depth(), false)
|
eventNID, snapNID, err := tab.InsertEvent(ctx, nil, 1, 1, 1, ev.EventID(), nil, ev.Depth(), false)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
gotEventNID, gotSnapNID, err := tab.SelectEvent(ctx, nil, ev.EventID())
|
gotEventNID, gotSnapNID, err := tab.SelectEvent(ctx, nil, ev.EventID())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -75,7 +73,6 @@ func Test_EventsTable(t *testing.T) {
|
||||||
assert.True(t, sentToOutput)
|
assert.True(t, sentToOutput)
|
||||||
|
|
||||||
eventIDs = append(eventIDs, ev.EventID())
|
eventIDs = append(eventIDs, ev.EventID())
|
||||||
wantEventReferences = append(wantEventReferences, ev.EventReference())
|
|
||||||
|
|
||||||
// Set the stateSnapshot to 2 for some events to verify they are returned later
|
// Set the stateSnapshot to 2 for some events to verify they are returned later
|
||||||
stateSnapshot := 0
|
stateSnapshot := 0
|
||||||
|
@ -97,8 +94,8 @@ func Test_EventsTable(t *testing.T) {
|
||||||
}
|
}
|
||||||
wantStateAtEvent = append(wantStateAtEvent, stateAtEvent)
|
wantStateAtEvent = append(wantStateAtEvent, stateAtEvent)
|
||||||
wantStateAtEventAndRefs = append(wantStateAtEventAndRefs, types.StateAtEventAndReference{
|
wantStateAtEventAndRefs = append(wantStateAtEventAndRefs, types.StateAtEventAndReference{
|
||||||
StateAtEvent: stateAtEvent,
|
StateAtEvent: stateAtEvent,
|
||||||
EventReference: ev.EventReference(),
|
EventID: ev.EventID(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,10 +137,6 @@ func Test_EventsTable(t *testing.T) {
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
references, err := tab.BulkSelectEventReference(ctx, nil, nids)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, wantEventReferences, references)
|
|
||||||
|
|
||||||
stateAndRefs, err := tab.BulkSelectStateAtEventAndReference(ctx, nil, nids)
|
stateAndRefs, err := tab.BulkSelectStateAtEventAndReference(ctx, nil, nids)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, wantStateAtEventAndRefs, stateAndRefs)
|
assert.Equal(t, wantStateAtEventAndRefs, stateAndRefs)
|
||||||
|
|
|
@ -42,7 +42,7 @@ type Events interface {
|
||||||
InsertEvent(
|
InsertEvent(
|
||||||
ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, eventTypeNID types.EventTypeNID,
|
ctx context.Context, txn *sql.Tx, roomNID types.RoomNID, eventTypeNID types.EventTypeNID,
|
||||||
eventStateKeyNID types.EventStateKeyNID, eventID string,
|
eventStateKeyNID types.EventStateKeyNID, eventID string,
|
||||||
referenceSHA256 []byte, authEventNIDs []types.EventNID, depth int64, isRejected bool,
|
authEventNIDs []types.EventNID, depth int64, isRejected bool,
|
||||||
) (types.EventNID, types.StateSnapshotNID, error)
|
) (types.EventNID, types.StateSnapshotNID, error)
|
||||||
SelectEvent(ctx context.Context, txn *sql.Tx, eventID string) (types.EventNID, types.StateSnapshotNID, error)
|
SelectEvent(ctx context.Context, txn *sql.Tx, eventID string) (types.EventNID, types.StateSnapshotNID, error)
|
||||||
BulkSelectSnapshotsFromEventIDs(ctx context.Context, txn *sql.Tx, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
BulkSelectSnapshotsFromEventIDs(ctx context.Context, txn *sql.Tx, eventIDs []string) (map[types.StateSnapshotNID][]string, error)
|
||||||
|
@ -59,7 +59,6 @@ type Events interface {
|
||||||
UpdateEventSentToOutput(ctx context.Context, txn *sql.Tx, eventNID types.EventNID) error
|
UpdateEventSentToOutput(ctx context.Context, txn *sql.Tx, eventNID types.EventNID) error
|
||||||
SelectEventID(ctx context.Context, txn *sql.Tx, eventNID types.EventNID) (eventID string, err error)
|
SelectEventID(ctx context.Context, txn *sql.Tx, eventNID types.EventNID) (eventID string, err error)
|
||||||
BulkSelectStateAtEventAndReference(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) ([]types.StateAtEventAndReference, error)
|
BulkSelectStateAtEventAndReference(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) ([]types.StateAtEventAndReference, error)
|
||||||
BulkSelectEventReference(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) ([]gomatrixserverlib.EventReference, error)
|
|
||||||
// BulkSelectEventID returns a map from numeric event ID to string event ID.
|
// BulkSelectEventID returns a map from numeric event ID to string event ID.
|
||||||
BulkSelectEventID(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) (map[types.EventNID]string, error)
|
BulkSelectEventID(ctx context.Context, txn *sql.Tx, eventNIDs []types.EventNID) (map[types.EventNID]string, error)
|
||||||
// BulkSelectEventNIDs returns a map from string event ID to numeric event ID.
|
// BulkSelectEventNIDs returns a map from string event ID to numeric event ID.
|
||||||
|
@ -113,10 +112,10 @@ type RoomAliases interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PreviousEvents interface {
|
type PreviousEvents interface {
|
||||||
InsertPreviousEvent(ctx context.Context, txn *sql.Tx, previousEventID string, previousEventReferenceSHA256 []byte, eventNID types.EventNID) error
|
InsertPreviousEvent(ctx context.Context, txn *sql.Tx, previousEventID string, eventNID types.EventNID) error
|
||||||
// Check if the event reference exists
|
// Check if the event reference exists
|
||||||
// Returns sql.ErrNoRows if the event reference doesn't exist.
|
// Returns sql.ErrNoRows if the event reference doesn't exist.
|
||||||
SelectPreviousEventExists(ctx context.Context, txn *sql.Tx, eventID string, eventReferenceSHA256 []byte) error
|
SelectPreviousEventExists(ctx context.Context, txn *sql.Tx, eventID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Invites interface {
|
type Invites interface {
|
||||||
|
|
|
@ -45,17 +45,17 @@ func TestPreviousEventsTable(t *testing.T) {
|
||||||
defer close()
|
defer close()
|
||||||
|
|
||||||
for _, x := range room.Events() {
|
for _, x := range room.Events() {
|
||||||
for _, prevEvent := range x.PrevEvents() {
|
for _, eventID := range x.PrevEventIDs() {
|
||||||
err := tab.InsertPreviousEvent(ctx, nil, prevEvent.EventID, prevEvent.EventSHA256, 1)
|
err := tab.InsertPreviousEvent(ctx, nil, eventID, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = tab.SelectPreviousEventExists(ctx, nil, prevEvent.EventID, prevEvent.EventSHA256)
|
err = tab.SelectPreviousEventExists(ctx, nil, eventID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomString with a correct EventSHA256 should fail and return sql.ErrNoRows
|
// RandomString should fail and return sql.ErrNoRows
|
||||||
err := tab.SelectPreviousEventExists(ctx, nil, util.RandomString(16), room.Events()[0].EventReference().EventSHA256)
|
err := tab.SelectPreviousEventExists(ctx, nil, util.RandomString(16))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ func (s StateAtEvent) IsStateEvent() bool {
|
||||||
// The StateAtEvent is used to construct the current state of the room from the latest events.
|
// The StateAtEvent is used to construct the current state of the room from the latest events.
|
||||||
type StateAtEventAndReference struct {
|
type StateAtEventAndReference struct {
|
||||||
StateAtEvent
|
StateAtEvent
|
||||||
gomatrixserverlib.EventReference
|
EventID string
|
||||||
}
|
}
|
||||||
|
|
||||||
type StateAtEventAndReferences []StateAtEventAndReference
|
type StateAtEventAndReferences []StateAtEventAndReference
|
||||||
|
|
|
@ -75,7 +75,7 @@ func NewRoom(t *testing.T, creator *User, modifiers ...roomModifier) *Room {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) MustGetAuthEventRefsForEvent(t *testing.T, needed gomatrixserverlib.StateNeeded) []gomatrixserverlib.EventReference {
|
func (r *Room) MustGetAuthEventRefsForEvent(t *testing.T, needed gomatrixserverlib.StateNeeded) []string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
a, err := needed.AuthEventReferences(&r.authEvents)
|
a, err := needed.AuthEventReferences(&r.authEvents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -176,7 +176,7 @@ func (r *Room) CreateEvent(t *testing.T, creator *User, eventType string, conten
|
||||||
t.Fatalf("CreateEvent[%s]: failed to SetContent: %s", eventType, err)
|
t.Fatalf("CreateEvent[%s]: failed to SetContent: %s", eventType, err)
|
||||||
}
|
}
|
||||||
if depth > 1 {
|
if depth > 1 {
|
||||||
builder.PrevEvents = []gomatrixserverlib.EventReference{r.events[len(r.events)-1].EventReference()}
|
builder.PrevEvents = []string{r.events[len(r.events)-1].EventID()}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = builder.AddAuthEvents(&r.authEvents)
|
err = builder.AddAuthEvents(&r.authEvents)
|
||||||
|
|
Loading…
Reference in a new issue