diff --git a/src/github.com/matrix-org/dendrite/roomserver/storage/sql.go b/src/github.com/matrix-org/dendrite/roomserver/storage/sql.go index 4efafb02f..d90a5320d 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/storage/sql.go +++ b/src/github.com/matrix-org/dendrite/roomserver/storage/sql.go @@ -138,6 +138,9 @@ const eventTypesSchema = ` -- It also means that the numeric IDs for common event types should be -- consistent between different instances which might make ad-hoc debugging -- easier. +-- Other event types are automatically assigned numeric IDs starting from 2**16. +-- This leaves room to add more pre-assigned numeric IDs and clearly separates +-- the automatically assigned IDs from the pre-assigned IDs. CREATE SEQUENCE IF NOT EXISTS event_type_nid_seq START 65536; CREATE TABLE IF NOT EXISTS event_types ( -- Local numeric ID for the event type. @@ -155,6 +158,14 @@ INSERT INTO event_types (event_type_nid, event_type) VALUES (7, 'm.room.history_visibility') ON CONFLICT DO NOTHING; ` +// Assign a new numeric event type ID. +// The usual case is that the event type is not in the database. +// In that case the ID will be assigned using the next value from the sequence. +// We use `RETURNING` to tell postgres to return the assigned ID. +// But it's possible that the type was added in a query that raced with us. +// This will result in a conflict on the event_type_unique constraint. +// We peform a update that does nothing rather that doing nothing at all because +// postgres won't return anything unless we touch a row in the table. const insertEventTypeNIDSQL = "" + "INSERT INTO event_types (event_type) VALUES ($1)" + " ON CONFLICT ON CONSTRAINT event_type_unique" + @@ -200,6 +211,9 @@ const eventStateKeysSchema = ` -- string arrays which may help reduce GC pressure. -- Well known state keys are pre-assigned numeric IDs: -- 1 -> "" (the empty string) +-- Other state keys are automatically assigned numeric IDs starting from 2**16. +-- This leaves room to add more pre-assigned numeric IDs and clearly separates +-- the automatically assigned IDs from the pre-assigned IDs. CREATE SEQUENCE IF NOT EXISTS event_state_key_nid_seq START 65536; CREATE TABLE IF NOT EXISTS event_state_keys ( -- Local numeric ID for the state key. @@ -210,6 +224,7 @@ INSERT INTO event_state_keys (event_state_key_nid, event_state_key) VALUES (1, '') ON CONFLICT DO NOTHING; ` +// Same as insertEventTypeNIDSQL const insertEventStateKeyNIDSQL = "" + "INSERT INTO event_state_keys (event_state_key) VALUES ($1)" + " ON CONFLICT ON CONSTRAINT event_state_key_unique" + @@ -257,6 +272,7 @@ CREATE TABLE IF NOT EXISTS rooms ( ); ` +// Same as insertEventTypeNIDSQL const insertRoomNIDSQL = "" + "INSERT INTO rooms (room_id) VALUES ($1)" + " ON CONFLICT ON CONSTRAINT room_id_unique" + diff --git a/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go index 2b80ba346..9bf206a88 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go +++ b/src/github.com/matrix-org/dendrite/roomserver/storage/storage.go @@ -72,32 +72,35 @@ func (d *Database) StoreEvent(event gomatrixserverlib.Event) error { return d.statements.insertEventJSON(eventNID, event.JSON()) } -func (d *Database) assignRoomNID(roomID string) (roomNID int64, err error) { - if roomNID, err = d.statements.selectRoomNID(roomID); err != nil { - return +func (d *Database) assignRoomNID(roomID string) (int64, error) { + roomNID, err := d.statements.selectRoomNID(roomID) + if err != nil { + return 0, err } if roomNID == 0 { return d.statements.insertRoomNID(roomID) } - return + return roomNID, nil } -func (d *Database) assignEventTypeNID(eventType string) (eventTypeNID int64, err error) { - if eventTypeNID, err = d.statements.selectEventTypeNID(eventType); err != nil { - return +func (d *Database) assignEventTypeNID(eventType string) (int64, error) { + eventTypeNID, err := d.statements.selectEventTypeNID(eventType) + if err != nil { + return 0, err } if eventTypeNID == 0 { return d.statements.insertEventTypeNID(eventType) } - return + return eventTypeNID, nil } -func (d *Database) assignStateKeyNID(eventStateKey string) (eventStateKeyNID int64, err error) { - if eventStateKeyNID, err = d.statements.selectEventStateKeyNID(eventStateKey); err != nil { - return +func (d *Database) assignStateKeyNID(eventStateKey string) (int64, error) { + eventStateKeyNID, err := d.statements.selectEventStateKeyNID(eventStateKey) + if err != nil { + return 0, err } if eventStateKeyNID == 0 { return d.statements.insertEventStateKeyNID(eventStateKey) } - return + return eventStateKeyNID, nil }