Assign room NIDs, event type NIDs and state key NIDs outside of database transactions (#2265)

* Assign room NIDs and state key NIDs outside of database transactions

* In roomserver storage package too

* Don't take a `txn` parameter, clean up SQLite
This commit is contained in:
Neil Alexander 2022-03-17 18:24:27 +00:00 committed by GitHub
parent 4e64c270db
commit 191486438c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 62 deletions

View file

@ -26,12 +26,12 @@ func NewMembershipUpdater(
var targetUserNID types.EventStateKeyNID var targetUserNID types.EventStateKeyNID
var err error var err error
err = d.Writer.Do(d.DB, txn, func(txn *sql.Tx) error { err = d.Writer.Do(d.DB, txn, func(txn *sql.Tx) error {
roomNID, err = d.assignRoomNID(ctx, txn, roomID, roomVersion) roomNID, err = d.assignRoomNID(ctx, roomID, roomVersion)
if err != nil { if err != nil {
return err return err
} }
targetUserNID, err = d.assignStateKeyNID(ctx, txn, targetUserID) targetUserNID, err = d.assignStateKeyNID(ctx, targetUserID)
if err != nil { if err != nil {
return err return err
} }
@ -95,7 +95,7 @@ func (u *MembershipUpdater) IsKnock() bool {
func (u *MembershipUpdater) SetToInvite(event *gomatrixserverlib.Event) (bool, error) { func (u *MembershipUpdater) SetToInvite(event *gomatrixserverlib.Event) (bool, error) {
var inserted bool var inserted bool
err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error { err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error {
senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, event.Sender()) senderUserNID, err := u.d.assignStateKeyNID(u.ctx, event.Sender())
if err != nil { if err != nil {
return fmt.Errorf("u.d.AssignStateKeyNID: %w", err) return fmt.Errorf("u.d.AssignStateKeyNID: %w", err)
} }
@ -120,7 +120,7 @@ func (u *MembershipUpdater) SetToJoin(senderUserID string, eventID string, isUpd
var inviteEventIDs []string var inviteEventIDs []string
err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error { err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error {
senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, senderUserID) senderUserNID, err := u.d.assignStateKeyNID(u.ctx, senderUserID)
if err != nil { if err != nil {
return fmt.Errorf("u.d.AssignStateKeyNID: %w", err) return fmt.Errorf("u.d.AssignStateKeyNID: %w", err)
} }
@ -158,7 +158,7 @@ func (u *MembershipUpdater) SetToLeave(senderUserID string, eventID string) ([]s
var inviteEventIDs []string var inviteEventIDs []string
err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error { err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error {
senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, senderUserID) senderUserNID, err := u.d.assignStateKeyNID(u.ctx, senderUserID)
if err != nil { if err != nil {
return fmt.Errorf("u.d.AssignStateKeyNID: %w", err) return fmt.Errorf("u.d.AssignStateKeyNID: %w", err)
} }
@ -190,7 +190,7 @@ func (u *MembershipUpdater) SetToLeave(senderUserID string, eventID string) ([]s
func (u *MembershipUpdater) SetToKnock(event *gomatrixserverlib.Event) (bool, error) { func (u *MembershipUpdater) SetToKnock(event *gomatrixserverlib.Event) (bool, error) {
var inserted bool var inserted bool
err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error { err := u.d.Writer.Do(u.d.DB, u.txn, func(txn *sql.Tx) error {
senderUserNID, err := u.d.assignStateKeyNID(u.ctx, u.txn, event.Sender()) senderUserNID, err := u.d.assignStateKeyNID(u.ctx, event.Sender())
if err != nil { if err != nil {
return fmt.Errorf("u.d.AssignStateKeyNID: %w", err) return fmt.Errorf("u.d.AssignStateKeyNID: %w", err)
} }

View file

@ -379,7 +379,7 @@ func (d *Database) RemoveRoomAlias(ctx context.Context, alias string) error {
func (d *Database) GetMembership(ctx context.Context, roomNID types.RoomNID, requestSenderUserID string) (membershipEventNID types.EventNID, stillInRoom, isRoomforgotten bool, err error) { func (d *Database) GetMembership(ctx context.Context, roomNID types.RoomNID, requestSenderUserID string) (membershipEventNID types.EventNID, stillInRoom, isRoomforgotten bool, err error) {
var requestSenderUserNID types.EventStateKeyNID var requestSenderUserNID types.EventStateKeyNID
err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { err = d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
requestSenderUserNID, err = d.assignStateKeyNID(ctx, txn, requestSenderUserID) requestSenderUserNID, err = d.assignStateKeyNID(ctx, requestSenderUserID)
return err return err
}) })
if err != nil { if err != nil {
@ -563,11 +563,11 @@ func (d *Database) storeEvent(
return fmt.Errorf("extractRoomVersionFromCreateEvent: %w", err) return fmt.Errorf("extractRoomVersionFromCreateEvent: %w", err)
} }
if roomNID, err = d.assignRoomNID(ctx, txn, event.RoomID(), roomVersion); err != nil { if roomNID, err = d.assignRoomNID(ctx, event.RoomID(), roomVersion); err != nil {
return fmt.Errorf("d.assignRoomNID: %w", err) return fmt.Errorf("d.assignRoomNID: %w", err)
} }
if eventTypeNID, err = d.assignEventTypeNID(ctx, txn, event.Type()); err != nil { if eventTypeNID, err = d.assignEventTypeNID(ctx, event.Type()); err != nil {
return fmt.Errorf("d.assignEventTypeNID: %w", err) return fmt.Errorf("d.assignEventTypeNID: %w", err)
} }
@ -575,7 +575,7 @@ func (d *Database) storeEvent(
// Assigned a numeric ID for the state_key if there is one present. // Assigned a numeric ID for the state_key if there is one present.
// Otherwise set the numeric ID for the state_key to 0. // Otherwise set the numeric ID for the state_key to 0.
if eventStateKey != nil { if eventStateKey != nil {
if eventStateKeyNID, err = d.assignStateKeyNID(ctx, txn, *eventStateKey); err != nil { if eventStateKeyNID, err = d.assignStateKeyNID(ctx, *eventStateKey); err != nil {
return fmt.Errorf("d.assignStateKeyNID: %w", err) return fmt.Errorf("d.assignStateKeyNID: %w", err)
} }
} }
@ -701,52 +701,51 @@ func (d *Database) MissingAuthPrevEvents(
} }
func (d *Database) assignRoomNID( func (d *Database) assignRoomNID(
ctx context.Context, txn *sql.Tx, ctx context.Context, roomID string, roomVersion gomatrixserverlib.RoomVersion,
roomID string, roomVersion gomatrixserverlib.RoomVersion,
) (types.RoomNID, error) { ) (types.RoomNID, error) {
if roomInfo, ok := d.Cache.GetRoomInfo(roomID); ok { if roomInfo, ok := d.Cache.GetRoomInfo(roomID); ok {
return roomInfo.RoomNID, nil return roomInfo.RoomNID, nil
} }
// Check if we already have a numeric ID in the database. // Check if we already have a numeric ID in the database.
roomNID, err := d.RoomsTable.SelectRoomNID(ctx, txn, roomID) roomNID, err := d.RoomsTable.SelectRoomNID(ctx, nil, roomID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// We don't have a numeric ID so insert one into the database. // We don't have a numeric ID so insert one into the database.
roomNID, err = d.RoomsTable.InsertRoomNID(ctx, txn, roomID, roomVersion) roomNID, err = d.RoomsTable.InsertRoomNID(ctx, nil, roomID, roomVersion)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// We raced with another insert so run the select again. // We raced with another insert so run the select again.
roomNID, err = d.RoomsTable.SelectRoomNID(ctx, txn, roomID) roomNID, err = d.RoomsTable.SelectRoomNID(ctx, nil, roomID)
} }
} }
return roomNID, err return roomNID, err
} }
func (d *Database) assignEventTypeNID( func (d *Database) assignEventTypeNID(
ctx context.Context, txn *sql.Tx, eventType string, ctx context.Context, eventType string,
) (types.EventTypeNID, error) { ) (types.EventTypeNID, error) {
// Check if we already have a numeric ID in the database. // Check if we already have a numeric ID in the database.
eventTypeNID, err := d.EventTypesTable.SelectEventTypeNID(ctx, txn, eventType) eventTypeNID, err := d.EventTypesTable.SelectEventTypeNID(ctx, nil, eventType)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// We don't have a numeric ID so insert one into the database. // We don't have a numeric ID so insert one into the database.
eventTypeNID, err = d.EventTypesTable.InsertEventTypeNID(ctx, txn, eventType) eventTypeNID, err = d.EventTypesTable.InsertEventTypeNID(ctx, nil, eventType)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// We raced with another insert so run the select again. // We raced with another insert so run the select again.
eventTypeNID, err = d.EventTypesTable.SelectEventTypeNID(ctx, txn, eventType) eventTypeNID, err = d.EventTypesTable.SelectEventTypeNID(ctx, nil, eventType)
} }
} }
return eventTypeNID, err return eventTypeNID, err
} }
func (d *Database) assignStateKeyNID( func (d *Database) assignStateKeyNID(
ctx context.Context, txn *sql.Tx, eventStateKey string, ctx context.Context, eventStateKey string,
) (types.EventStateKeyNID, error) { ) (types.EventStateKeyNID, error) {
// Check if we already have a numeric ID in the database. // Check if we already have a numeric ID in the database.
eventStateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, txn, eventStateKey) eventStateKeyNID, err := d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, eventStateKey)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// We don't have a numeric ID so insert one into the database. // We don't have a numeric ID so insert one into the database.
eventStateKeyNID, err = d.EventStateKeysTable.InsertEventStateKeyNID(ctx, txn, eventStateKey) eventStateKeyNID, err = d.EventStateKeysTable.InsertEventStateKeyNID(ctx, nil, eventStateKey)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
// We raced with another insert so run the select again. // We raced with another insert so run the select again.
eventStateKeyNID, err = d.EventStateKeysTable.SelectEventStateKeyNID(ctx, txn, eventStateKey) eventStateKeyNID, err = d.EventStateKeysTable.SelectEventStateKeyNID(ctx, nil, eventStateKey)
} }
} }
return eventStateKeyNID, err return eventStateKeyNID, err

View file

@ -18,6 +18,7 @@ package sqlite3
import ( import (
"context" "context"
"database/sql" "database/sql"
"fmt"
"strings" "strings"
"github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/internal"
@ -39,7 +40,8 @@ const eventStateKeysSchema = `
// Same as insertEventTypeNIDSQL // Same as insertEventTypeNIDSQL
const insertEventStateKeyNIDSQL = ` const insertEventStateKeyNIDSQL = `
INSERT INTO roomserver_event_state_keys (event_state_key) VALUES ($1) INSERT INTO roomserver_event_state_keys (event_state_key) VALUES ($1)
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING
RETURNING event_state_key_nid;
` `
const selectEventStateKeyNIDSQL = ` const selectEventStateKeyNIDSQL = `
@ -89,17 +91,12 @@ func prepareEventStateKeysTable(db *sql.DB) (tables.EventStateKeys, error) {
func (s *eventStateKeyStatements) InsertEventStateKeyNID( func (s *eventStateKeyStatements) InsertEventStateKeyNID(
ctx context.Context, txn *sql.Tx, eventStateKey string, ctx context.Context, txn *sql.Tx, eventStateKey string,
) (types.EventStateKeyNID, error) { ) (eventStateKeyNID types.EventStateKeyNID, err error) {
insertStmt := sqlutil.TxStmt(txn, s.insertEventStateKeyNIDStmt) insertStmt := sqlutil.TxStmt(txn, s.insertEventStateKeyNIDStmt)
res, err := insertStmt.ExecContext(ctx, eventStateKey) if err := insertStmt.QueryRowContext(ctx, eventStateKey).Scan(&eventStateKeyNID); err != nil {
if err != nil { return 0, fmt.Errorf("resultStmt.QueryRowContext.Scan: %w", err)
return 0, err
} }
eventStateKeyNID, err := res.LastInsertId() return
if err != nil {
return 0, err
}
return types.EventStateKeyNID(eventStateKeyNID), err
} }
func (s *eventStateKeyStatements) SelectEventStateKeyNID( func (s *eventStateKeyStatements) SelectEventStateKeyNID(

View file

@ -57,12 +57,8 @@ const eventTypesSchema = `
// to the indexes. // to the indexes.
const insertEventTypeNIDSQL = ` const insertEventTypeNIDSQL = `
INSERT INTO roomserver_event_types (event_type) VALUES ($1) INSERT INTO roomserver_event_types (event_type) VALUES ($1)
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING
` RETURNING event_type_nid;
const insertEventTypeNIDResultSQL = `
SELECT event_type_nid FROM roomserver_event_types
WHERE rowid = last_insert_rowid();
` `
const selectEventTypeNIDSQL = ` const selectEventTypeNIDSQL = `
@ -77,11 +73,10 @@ const bulkSelectEventTypeNIDSQL = `
` `
type eventTypeStatements struct { type eventTypeStatements struct {
db *sql.DB db *sql.DB
insertEventTypeNIDStmt *sql.Stmt insertEventTypeNIDStmt *sql.Stmt
insertEventTypeNIDResultStmt *sql.Stmt selectEventTypeNIDStmt *sql.Stmt
selectEventTypeNIDStmt *sql.Stmt bulkSelectEventTypeNIDStmt *sql.Stmt
bulkSelectEventTypeNIDStmt *sql.Stmt
} }
func createEventTypesTable(db *sql.DB) error { func createEventTypesTable(db *sql.DB) error {
@ -96,7 +91,6 @@ func prepareEventTypesTable(db *sql.DB) (tables.EventTypes, error) {
return s, sqlutil.StatementList{ return s, sqlutil.StatementList{
{&s.insertEventTypeNIDStmt, insertEventTypeNIDSQL}, {&s.insertEventTypeNIDStmt, insertEventTypeNIDSQL},
{&s.insertEventTypeNIDResultStmt, insertEventTypeNIDResultSQL},
{&s.selectEventTypeNIDStmt, selectEventTypeNIDSQL}, {&s.selectEventTypeNIDStmt, selectEventTypeNIDSQL},
{&s.bulkSelectEventTypeNIDStmt, bulkSelectEventTypeNIDSQL}, {&s.bulkSelectEventTypeNIDStmt, bulkSelectEventTypeNIDSQL},
}.Prepare(db) }.Prepare(db)
@ -104,18 +98,12 @@ func prepareEventTypesTable(db *sql.DB) (tables.EventTypes, error) {
func (s *eventTypeStatements) InsertEventTypeNID( func (s *eventTypeStatements) InsertEventTypeNID(
ctx context.Context, txn *sql.Tx, eventType string, ctx context.Context, txn *sql.Tx, eventType string,
) (types.EventTypeNID, error) { ) (eventTypeNID types.EventTypeNID, err error) {
var eventTypeNID int64
insertStmt := sqlutil.TxStmt(txn, s.insertEventTypeNIDStmt) insertStmt := sqlutil.TxStmt(txn, s.insertEventTypeNIDStmt)
resultStmt := sqlutil.TxStmt(txn, s.insertEventTypeNIDResultStmt) if err = insertStmt.QueryRowContext(ctx, eventType).Scan(&eventTypeNID); err != nil {
_, err := insertStmt.ExecContext(ctx, eventType)
if err != nil {
return 0, fmt.Errorf("insertStmt.ExecContext: %w", err)
}
if err = resultStmt.QueryRowContext(ctx).Scan(&eventTypeNID); err != nil {
return 0, fmt.Errorf("resultStmt.QueryRowContext.Scan: %w", err) return 0, fmt.Errorf("resultStmt.QueryRowContext.Scan: %w", err)
} }
return types.EventTypeNID(eventTypeNID), err return
} }
func (s *eventTypeStatements) SelectEventTypeNID( func (s *eventTypeStatements) SelectEventTypeNID(

View file

@ -43,7 +43,8 @@ const roomsSchema = `
// Same as insertEventTypeNIDSQL // Same as insertEventTypeNIDSQL
const insertRoomNIDSQL = ` const insertRoomNIDSQL = `
INSERT INTO roomserver_rooms (room_id, room_version) VALUES ($1, $2) INSERT INTO roomserver_rooms (room_id, room_version) VALUES ($1, $2)
ON CONFLICT DO NOTHING; ON CONFLICT DO NOTHING
RETURNING room_nid;
` `
const selectRoomNIDSQL = "" + const selectRoomNIDSQL = "" +
@ -151,13 +152,8 @@ func (s *roomStatements) InsertRoomNID(
roomID string, roomVersion gomatrixserverlib.RoomVersion, roomID string, roomVersion gomatrixserverlib.RoomVersion,
) (roomNID types.RoomNID, err error) { ) (roomNID types.RoomNID, err error) {
insertStmt := sqlutil.TxStmt(txn, s.insertRoomNIDStmt) insertStmt := sqlutil.TxStmt(txn, s.insertRoomNIDStmt)
_, err = insertStmt.ExecContext(ctx, roomID, roomVersion) if err = insertStmt.QueryRowContext(ctx, roomID, roomVersion).Scan(&roomNID); err != nil {
if err != nil { return 0, fmt.Errorf("resultStmt.QueryRowContext.Scan: %w", err)
return 0, fmt.Errorf("insertStmt.ExecContext: %w", err)
}
roomNID, err = s.SelectRoomNID(ctx, txn, roomID)
if err != nil {
return 0, fmt.Errorf("s.SelectRoomNID: %w", err)
} }
return return
} }