-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #351 from matrix-org/dmr/cleanup-dead-invites
- Loading branch information
Showing
2 changed files
with
147 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
-- +goose Up | ||
-- +goose StatementBegin | ||
WITH | ||
dead_invites(user_id, room_id) AS ( | ||
SELECT syncv3_invites.user_id, syncv3_invites.room_id | ||
FROM syncv3_invites | ||
JOIN syncv3_rooms USING (room_id) | ||
JOIN syncv3_snapshots ON (syncv3_snapshots.snapshot_id = syncv3_rooms.current_snapshot_id) | ||
JOIN syncv3_events ON ( | ||
event_nid = ANY (membership_events) | ||
AND state_key = syncv3_invites.user_id | ||
AND NOT (membership = 'invite' OR membership = '_invite') | ||
) | ||
) | ||
DELETE FROM syncv3_invites | ||
WHERE (user_id, room_id) IN (SELECT * FROM dead_invites); | ||
-- +goose StatementEnd | ||
|
||
-- +goose Down | ||
-- +goose StatementBegin | ||
-- no-op | ||
-- +goose StatementEnd |
125 changes: 125 additions & 0 deletions
125
state/migrations/20231019153023_cleanup_dead_invites_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package migrations | ||
|
||
import ( | ||
"embed" | ||
_ "embed" | ||
"encoding/json" | ||
_ "github.com/lib/pq" | ||
"github.com/matrix-org/sliding-sync/state" | ||
"github.com/pressly/goose/v3" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
//go:embed 20231019153023_cleanup_dead_invites.sql | ||
var deadInviteMigration embed.FS | ||
|
||
func TestDeadInviteCleanup(t *testing.T) { | ||
db, close := connectToDB(t) | ||
defer close() | ||
store := state.NewStorageWithDB(db, false) | ||
|
||
t.Log("Alice and Bob both have invites to rooms X and Y. Chris has an invite to room Z.") | ||
_, err := store.DB.Exec(` | ||
INSERT INTO syncv3_invites(user_id, room_id, invite_state) | ||
VALUES ('@alice:test', '!x', '[]'), | ||
('@alice:test', '!y', '[]'), | ||
('@bob:test' , '!x', '[]'), | ||
('@bob:test' , '!y', '[]'), | ||
('@chris:test', '!z', '[]'); | ||
`) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
t.Log("Alice is joined to room X; Bob banned from room Y. Chris isn't joined to any rooms.") | ||
_, err = store.DB.Exec(` | ||
INSERT INTO syncv3_events( | ||
event_nid, | ||
event_id, | ||
before_state_snapshot_id, | ||
event_replaces_nid, | ||
room_id, | ||
event_type, | ||
state_key, | ||
prev_batch, | ||
membership, | ||
is_state, | ||
event, | ||
missing_previous | ||
) | ||
VALUES (1, '$alice-join-x' , 0, 0, '!x', 'm.room.member', '@alice:test', '', 'join' , false, '', false), | ||
(2, '$alice-invite-y', 0, 0, '!y', 'm.room.member', '@alice:test', '', 'invite', false, '', false), | ||
(3, '$bob-invite-x' , 0, 0, '!x', 'm.room.member', '@bob:test' , '', 'invite', false, '', false), | ||
(4, '$bob-ban-y' , 0, 0, '!y', 'm.room.member', '@bob:test' , '', 'ban' , false, '', false), | ||
(5, '$chris-invite-z', 0, 0, '!x', 'm.room.member', '@chris:test', '', 'invite', false, '', false); | ||
`) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
_, err = store.DB.Exec(` | ||
INSERT INTO syncv3_snapshots(snapshot_id, room_id, events, membership_events) | ||
VALUES (10, '!x', '{}', '{1,3}'), | ||
(11, '!y', '{}', '{2,4}'), | ||
(12, '!z', '{}', '{5}'); | ||
`) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
_, err = store.DB.Exec(` | ||
INSERT INTO syncv3_rooms(room_id, current_snapshot_id, is_encrypted, upgraded_room_id, predecessor_room_id, latest_nid, type) | ||
VALUES ('!x', '10', false, NULL, NULL, 3, NULL), | ||
('!y', '11', false, NULL, NULL, 4, NULL), | ||
('!z', '12', false, NULL, NULL, 5, NULL); | ||
`) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
t.Log("Run the migration.") | ||
goose.SetBaseFS(deadInviteMigration) | ||
err = goose.SetDialect("postgres") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
err = goose.Up(db.DB, ".") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
emptyInviteState := []json.RawMessage{} | ||
|
||
t.Log("Alice's invite to room X, and Bob's invite to room Y should have been deleted.") | ||
aliceInvites, err := store.InvitesTable.SelectAllInvitesForUser("@alice:test") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
assertInvites(t, "alice", aliceInvites, map[string][]json.RawMessage{ | ||
"!y": emptyInviteState, | ||
}) | ||
|
||
bobInvites, err := store.InvitesTable.SelectAllInvitesForUser("@bob:test") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
assertInvites(t, "bob", bobInvites, map[string][]json.RawMessage{ | ||
"!x": emptyInviteState, | ||
}) | ||
|
||
chrisInvites, err := store.InvitesTable.SelectAllInvitesForUser("@chris:test") | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
assertInvites(t, "chris", chrisInvites, map[string][]json.RawMessage{ | ||
"!z": emptyInviteState, | ||
}) | ||
|
||
} | ||
|
||
func assertInvites(t *testing.T, name string, got, want map[string][]json.RawMessage) { | ||
t.Helper() | ||
if !reflect.DeepEqual(got, want) { | ||
t.Errorf("Mismatched invites for %s: got %v want %v", name, got, want) | ||
} | ||
} |