Save the join membership event and updates it when necessary

This commit is contained in:
Brendan Abolivier 2017-08-17 17:59:30 +01:00
parent 7afed10dc0
commit 68aa5bce29
No known key found for this signature in database
GPG key ID: 8EF1500759F70623
4 changed files with 42 additions and 21 deletions

View file

@ -95,10 +95,9 @@ func updateMembership(
return nil, err return nil, err
} }
} }
if old == new { if old == new && new != "join" {
// If the membership is the same then nothing changed and we can return // If the membership is the same then nothing changed and we can return
// immediately. This should help speed up processing for display name // immediately.
// changes where the membership is "join" both before and after.
return updates, nil return updates, nil
} }
@ -152,16 +151,20 @@ func updateToInviteMembership(
func updateToJoinMembership( func updateToJoinMembership(
mu types.MembershipUpdater, add *gomatrixserverlib.Event, updates []api.OutputEvent, mu types.MembershipUpdater, add *gomatrixserverlib.Event, updates []api.OutputEvent,
) ([]api.OutputEvent, error) { ) ([]api.OutputEvent, error) {
// If the user is already marked as being joined then we can return immediately. // If the user is already marked as being joined, we call SetToJoin to update
// TODO: Is this code reachable given the "old != new" guard in updateMembership? // the event ID then we can return immediately. Retired is ignored as
if mu.IsJoin() { if mu.IsJoin() {
_, err := mu.SetToJoin(add.Sender(), add.EventID(), true)
if err != nil {
return nil, err
}
return updates, nil return updates, nil
} }
// When we mark a user as being joined we will invalidate any invites that // When we mark a user as being joined we will invalidate any invites that
// are active for that user. We notify the consumers that the invites have // are active for that user. We notify the consumers that the invites have
// been retired using a special event, even though they could infer this // been retired using a special event, even though they could infer this
// by studying the state changes in the room event stream. // by studying the state changes in the room event stream.
retired, err := mu.SetToJoin(add.Sender()) retired, err := mu.SetToJoin(add.Sender(), add.EventID(), false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -46,6 +46,11 @@ CREATE TABLE IF NOT EXISTS roomserver_membership (
-- The state the user is in within this room. -- The state the user is in within this room.
-- Default value is "membershipStateLeaveOrBan" -- Default value is "membershipStateLeaveOrBan"
membership_nid BIGINT NOT NULL DEFAULT 1, membership_nid BIGINT NOT NULL DEFAULT 1,
-- The ID of the "join" membership event.
-- This ID is updated if the join event gets updated (e.g. profile update).
-- This column is set to NULL if the user hasn't joined the room yet, e.g.
-- if the user was invited but hasn't joined yet.
event_id TEXT,
UNIQUE (room_nid, target_nid) UNIQUE (room_nid, target_nid)
); );
` `
@ -62,7 +67,7 @@ const selectMembershipForUpdateSQL = "" +
" WHERE room_nid = $1 AND target_nid = $2 FOR UPDATE" " WHERE room_nid = $1 AND target_nid = $2 FOR UPDATE"
const updateMembershipSQL = "" + const updateMembershipSQL = "" +
"UPDATE roomserver_membership SET sender_nid = $3, membership_nid = $4" + "UPDATE roomserver_membership SET sender_nid = $3, membership_nid = $4, event_id = $5" +
" WHERE room_nid = $1 AND target_nid = $2" " WHERE room_nid = $1 AND target_nid = $2"
type membershipStatements struct { type membershipStatements struct {
@ -103,9 +108,14 @@ func (s *membershipStatements) selectMembershipForUpdate(
func (s *membershipStatements) updateMembership( func (s *membershipStatements) updateMembership(
txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID, txn *sql.Tx, roomNID types.RoomNID, targetUserNID types.EventStateKeyNID,
senderUserNID types.EventStateKeyNID, membership membershipState, senderUserNID types.EventStateKeyNID, membership membershipState,
eventID string,
) error { ) error {
eID := sql.NullString{
String: eventID,
Valid: len(eventID) > 0,
}
_, err := txn.Stmt(s.updateMembershipStmt).Exec( _, err := txn.Stmt(s.updateMembershipStmt).Exec(
roomNID, targetUserNID, senderUserNID, membership, roomNID, targetUserNID, senderUserNID, membership, eID,
) )
return err return err
} }

View file

@ -435,7 +435,7 @@ func (u *membershipUpdater) SetToInvite(event gomatrixserverlib.Event) (bool, er
} }
if u.membership != membershipStateInvite { if u.membership != membershipStateInvite {
if err = u.d.statements.updateMembership( if err = u.d.statements.updateMembership(
u.txn, u.roomNID, u.targetUserNID, senderUserNID, membershipStateInvite, u.txn, u.roomNID, u.targetUserNID, senderUserNID, membershipStateInvite, "",
); err != nil { ); err != nil {
return false, err return false, err
} }
@ -444,24 +444,32 @@ func (u *membershipUpdater) SetToInvite(event gomatrixserverlib.Event) (bool, er
} }
// SetToJoin implements types.MembershipUpdater // SetToJoin implements types.MembershipUpdater
func (u *membershipUpdater) SetToJoin(senderUserID string) ([]string, error) { func (u *membershipUpdater) SetToJoin(senderUserID string, eventID string, isUpdate bool) ([]string, error) {
var inviteEventIDs []string
senderUserNID, err := u.d.assignStateKeyNID(u.txn, senderUserID) senderUserNID, err := u.d.assignStateKeyNID(u.txn, senderUserID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
inviteEventIDs, err := u.d.statements.updateInviteRetired(
u.txn, u.roomNID, u.targetUserNID, // If this is a join event update, there is no invite to update
) if !isUpdate {
if err != nil { inviteEventIDs, err = u.d.statements.updateInviteRetired(
return nil, err u.txn, u.roomNID, u.targetUserNID,
)
if err != nil {
return nil, err
}
} }
if u.membership != membershipStateJoin {
if u.membership != membershipStateJoin || isUpdate {
if err = u.d.statements.updateMembership( if err = u.d.statements.updateMembership(
u.txn, u.roomNID, u.targetUserNID, senderUserNID, membershipStateJoin, u.txn, u.roomNID, u.targetUserNID, senderUserNID, membershipStateJoin, eventID,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
} }
return inviteEventIDs, nil return inviteEventIDs, nil
} }
@ -479,7 +487,7 @@ func (u *membershipUpdater) SetToLeave(senderUserID string) ([]string, error) {
} }
if u.membership != membershipStateLeaveOrBan { if u.membership != membershipStateLeaveOrBan {
if err = u.d.statements.updateMembership( if err = u.d.statements.updateMembership(
u.txn, u.roomNID, u.targetUserNID, senderUserNID, membershipStateLeaveOrBan, u.txn, u.roomNID, u.targetUserNID, senderUserNID, membershipStateLeaveOrBan, "",
); err != nil { ); err != nil {
return nil, err return nil, err
} }

View file

@ -193,9 +193,9 @@ type MembershipUpdater interface {
// Set the state to invite. // Set the state to invite.
// Returns whether this invite needs to be sent // Returns whether this invite needs to be sent
SetToInvite(event gomatrixserverlib.Event) (needsSending bool, err error) SetToInvite(event gomatrixserverlib.Event) (needsSending bool, err error)
// Set the state to join. // Set the state to join or updates the event ID in the database.
// Returns a list of invite event IDs that this state change retired. // Returns a list of invite event IDs that this state change retired.
SetToJoin(senderUserID string) (inviteEventIDs []string, err error) SetToJoin(senderUserID string, eventID string, isUpdate bool) (inviteEventIDs []string, err error)
// Set the state to leave. // Set the state to leave.
// Returns a list of invite event IDs that this state change retired. // Returns a list of invite event IDs that this state change retired.
SetToLeave(senderUserID string) (inviteEventIDs []string, err error) SetToLeave(senderUserID string) (inviteEventIDs []string, err error)