BREAKING(db): Add predecessor_room_id to the rooms table

This tracks the room ID supplied in the create event.
This commit is contained in:
Kegan Dougal 2022-09-08 15:44:48 +01:00
parent 55ed63ef97
commit d591dd0584
3 changed files with 50 additions and 9 deletions

View File

@ -105,6 +105,7 @@ func (a *Accumulator) roomInfoDelta(roomID string, events []Event) RoomInfo {
isEncrypted := false isEncrypted := false
var upgradedRoomID *string var upgradedRoomID *string
var roomType *string var roomType *string
var pred *string
for _, ev := range events { for _, ev := range events {
if ev.Type == "m.room.encryption" && ev.StateKey == "" { if ev.Type == "m.room.encryption" && ev.StateKey == "" {
isEncrypted = true isEncrypted = true
@ -120,13 +121,19 @@ func (a *Accumulator) roomInfoDelta(roomID string, events []Event) RoomInfo {
if contentType.Exists() && contentType.Type == gjson.String { if contentType.Exists() && contentType.Type == gjson.String {
roomType = &contentType.Str roomType = &contentType.Str
} }
predecessorRoomID := gjson.GetBytes(ev.JSON, "content.predecessor.room_id").Str
if predecessorRoomID != "" {
pred = &predecessorRoomID
}
} }
} }
return RoomInfo{ return RoomInfo{
ID: roomID, ID: roomID,
IsEncrypted: isEncrypted, IsEncrypted: isEncrypted,
UpgradedRoomID: upgradedRoomID, UpgradedRoomID: upgradedRoomID,
Type: roomType, Type: roomType,
PredecessorRoomID: pred,
} }
} }

View File

@ -9,10 +9,11 @@ import (
) )
type RoomInfo struct { type RoomInfo struct {
ID string `db:"room_id"` ID string `db:"room_id"`
IsEncrypted bool `db:"is_encrypted"` IsEncrypted bool `db:"is_encrypted"`
UpgradedRoomID *string `db:"upgraded_room_id"` UpgradedRoomID *string `db:"upgraded_room_id"` // from the most recent valid tombstone event, or NULL
Type *string `db:"type"` PredecessorRoomID *string `db:"predecessor_room_id"` // from the create event
Type *string `db:"type"`
} }
// RoomsTable stores the current snapshot for a room. // RoomsTable stores the current snapshot for a room.
@ -26,6 +27,7 @@ func NewRoomsTable(db *sqlx.DB) *RoomsTable {
current_snapshot_id BIGINT NOT NULL, current_snapshot_id BIGINT NOT NULL,
is_encrypted BOOL NOT NULL DEFAULT FALSE, is_encrypted BOOL NOT NULL DEFAULT FALSE,
upgraded_room_id TEXT, upgraded_room_id TEXT,
predecessor_room_id TEXT,
latest_nid BIGINT NOT NULL DEFAULT 0, latest_nid BIGINT NOT NULL DEFAULT 0,
type TEXT -- nullable type TEXT -- nullable
); );
@ -34,7 +36,7 @@ func NewRoomsTable(db *sqlx.DB) *RoomsTable {
} }
func (t *RoomsTable) SelectRoomInfos(txn *sqlx.Tx) (infos []RoomInfo, err error) { func (t *RoomsTable) SelectRoomInfos(txn *sqlx.Tx) (infos []RoomInfo, err error) {
err = txn.Select(&infos, `SELECT room_id, is_encrypted, upgraded_room_id, type FROM syncv3_rooms`) err = txn.Select(&infos, `SELECT room_id, is_encrypted, upgraded_room_id, predecessor_room_id, type FROM syncv3_rooms`)
return return
} }
@ -65,6 +67,12 @@ func (t *RoomsTable) Upsert(txn *sqlx.Tx, info RoomInfo, snapshotID, latestNID i
doUpdate += fmt.Sprintf(", type = $%d", n) // should never be updated but you never know... doUpdate += fmt.Sprintf(", type = $%d", n) // should never be updated but you never know...
n++ n++
} }
if info.PredecessorRoomID != nil {
cols += ", predecessor_room_id"
vals += fmt.Sprintf(", $%d", n)
doUpdate += fmt.Sprintf(", predecessor_room_id = $%d", n)
n++
}
insertQuery := fmt.Sprintf(`INSERT INTO syncv3_rooms(%s) VALUES(%s) %s`, cols, vals, doUpdate) insertQuery := fmt.Sprintf(`INSERT INTO syncv3_rooms(%s) VALUES(%s) %s`, cols, vals, doUpdate)
args := []interface{}{ args := []interface{}{
info.ID, snapshotID, latestNID, info.ID, snapshotID, latestNID,
@ -75,6 +83,9 @@ func (t *RoomsTable) Upsert(txn *sqlx.Tx, info RoomInfo, snapshotID, latestNID i
if info.Type != nil { if info.Type != nil {
args = append(args, info.Type) args = append(args, info.Type)
} }
if info.PredecessorRoomID != nil {
args = append(args, *info.PredecessorRoomID)
}
_, err = txn.Exec(insertQuery, args...) _, err = txn.Exec(insertQuery, args...)
return err return err
} }

View File

@ -188,6 +188,29 @@ func TestRoomsTable(t *testing.T) {
if nidMap[untombstonedRoomID] != 1003 { // not 1002 as it should be updated by the subsequent update if nidMap[untombstonedRoomID] != 1003 { // not 1002 as it should be updated by the subsequent update
t.Errorf("LatestNIDs: got %v want 1003", nidMap[untombstonedRoomID]) t.Errorf("LatestNIDs: got %v want 1003", nidMap[untombstonedRoomID])
} }
// check predecessor can be set
sucessorRoomID := "!sucessorRoomID:localhost"
predecessorRoomID := "!predecessor:localhost"
if err = table.Upsert(txn, RoomInfo{
ID: sucessorRoomID,
PredecessorRoomID: &predecessorRoomID,
IsEncrypted: true,
}, 2222, 1); err != nil {
t.Fatalf("Failed to update current snapshot ID: %s", err)
}
// verify
ri := getRoomInfo(t, txn, table, sucessorRoomID)
if !ri.IsEncrypted {
t.Errorf("upgraded room did not set encryption bit")
}
if ri.PredecessorRoomID == nil {
t.Errorf("predecessor room is nil")
}
if *ri.PredecessorRoomID == sucessorRoomID {
t.Errorf("predecessor room got %v want %v", *ri.PredecessorRoomID, predecessorRoomID)
}
} }
func getRoomInfo(t *testing.T, txn *sqlx.Tx, table *RoomsTable, roomID string) RoomInfo { func getRoomInfo(t *testing.T, txn *sqlx.Tx, table *RoomsTable, roomID string) RoomInfo {