forked from MirrorHub/mautrix-whatsapp
Improve errors in state store migration edge cases
This commit is contained in:
parent
ab91d326fd
commit
3be9aa2319
13 changed files with 42 additions and 23 deletions
|
@ -43,7 +43,7 @@ type Config struct {
|
|||
MaxIdleConns int `yaml:"max_idle_conns"`
|
||||
} `yaml:"database"`
|
||||
|
||||
StateStore string `yaml:"state_store_path"`
|
||||
StateStore string `yaml:"state_store_path,omitempty"`
|
||||
|
||||
ID string `yaml:"id"`
|
||||
Bot struct {
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[0] = upgrade{"Initial schema", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[0] = upgrade{"Initial schema", func(tx *sql.Tx, ctx context) error {
|
||||
var byteType string
|
||||
if dialect == SQLite {
|
||||
if ctx.dialect == SQLite {
|
||||
byteType = "BLOB"
|
||||
} else {
|
||||
byteType = "bytea"
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[1] = upgrade{"Add ON DELETE CASCADE to message table", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
if dialect == SQLite {
|
||||
upgrades[1] = upgrade{"Add ON DELETE CASCADE to message table", func(tx *sql.Tx, ctx context) error {
|
||||
if ctx.dialect == SQLite {
|
||||
// SQLite doesn't support constraint updates, but it isn't that careful with constraints anyway.
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[2] = upgrade{"Add timestamp column to messages", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[2] = upgrade{"Add timestamp column to messages", func(tx *sql.Tx, ctx context) error {
|
||||
_, err := tx.Exec("ALTER TABLE message ADD COLUMN timestamp BIGINT NOT NULL DEFAULT 0")
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[3] = upgrade{"Add last_connection column to users", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[3] = upgrade{"Add last_connection column to users", func(tx *sql.Tx, ctx context) error {
|
||||
_, err := tx.Exec(`ALTER TABLE "user" ADD COLUMN last_connection BIGINT NOT NULL DEFAULT 0`)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
|
||||
func init() {
|
||||
var keys = []string{"imageMessage", "contactMessage", "locationMessage", "extendedTextMessage", "documentMessage", "audioMessage", "videoMessage"}
|
||||
upgrades[4] = upgrade{"Update message content to new protocol version. This may take a while.", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
rows, err := db.Query("SELECT mxid, content FROM message")
|
||||
upgrades[4] = upgrade{"Update message content to new protocol version. This may take a while.", func(tx *sql.Tx, ctx context) error {
|
||||
rows, err := ctx.db.Query("SELECT mxid, content FROM message")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[5] = upgrade{"Add columns to store custom puppet info", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[5] = upgrade{"Add columns to store custom puppet info", func(tx *sql.Tx, ctx context) error {
|
||||
_, err := tx.Exec(`ALTER TABLE puppet ADD COLUMN custom_mxid VARCHAR(255)`)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[6] = upgrade{"Add user-portal mapping table", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[6] = upgrade{"Add user-portal mapping table", func(tx *sql.Tx, ctx context) error {
|
||||
_, err := tx.Exec(`CREATE TABLE user_portal (
|
||||
user_jid VARCHAR(255),
|
||||
portal_jid VARCHAR(255),
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[7] = upgrade{"Add columns to store avatar MXC URIs", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[7] = upgrade{"Add columns to store avatar MXC URIs", func(tx *sql.Tx, ctx context) error {
|
||||
_, err := tx.Exec(`ALTER TABLE puppet ADD COLUMN avatar_url VARCHAR(255)`)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
upgrades[8] = upgrade{"Add columns to store portal in filtering community meta", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[8] = upgrade{"Add columns to store portal in filtering community meta", func(tx *sql.Tx, ctx context) error {
|
||||
_, err := tx.Exec(`ALTER TABLE user_portal ADD COLUMN in_community BOOLEAN NOT NULL DEFAULT FALSE`)
|
||||
return err
|
||||
}}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"maunium.net/go/mautrix"
|
||||
|
@ -78,15 +79,16 @@ func init() {
|
|||
user_id VARCHAR(255) PRIMARY KEY
|
||||
)`
|
||||
|
||||
upgrades[9] = upgrade{"Move state store to main DB", func(dialect Dialect, tx *sql.Tx, db *sql.DB) error {
|
||||
upgrades[9] = upgrade{"Move state store to main DB", func(tx *sql.Tx, ctx context) error {
|
||||
store := appservice.NewBasicStateStore().(*appservice.BasicStateStore)
|
||||
|
||||
if dialect == Postgres {
|
||||
if ctx.dialect == Postgres {
|
||||
roomStateTable = strings.Replace(roomStateTable, "TEXT", "JSONB", 1)
|
||||
}
|
||||
|
||||
if data, err := ioutil.ReadFile("mx-state.json"); err != nil {
|
||||
return err
|
||||
ctx.log.Debugln("mx-state.json not found, not migrating state store")
|
||||
return nil
|
||||
} else if err = json.Unmarshal(data, &store); err != nil {
|
||||
return err
|
||||
} else if _, err := tx.Exec(userProfileTable); err != nil {
|
||||
|
@ -101,6 +103,8 @@ func init() {
|
|||
return err
|
||||
} else if err = migratePowerLevels(tx, store.PowerLevels); err != nil {
|
||||
return err
|
||||
} else if err = os.Rename("mx-state.json", "mx-state.json.bak"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}}
|
||||
|
|
|
@ -15,11 +15,17 @@ const (
|
|||
SQLite
|
||||
)
|
||||
|
||||
type upgradeFunc func(Dialect, *sql.Tx, *sql.DB) error
|
||||
type upgradeFunc func(*sql.Tx, context) error
|
||||
|
||||
type context struct {
|
||||
dialect Dialect
|
||||
db *sql.DB
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
type upgrade struct {
|
||||
message string
|
||||
fn upgradeFunc
|
||||
fn upgradeFunc
|
||||
}
|
||||
|
||||
const NumberOfUpgrades = 10
|
||||
|
@ -28,7 +34,7 @@ var upgrades [NumberOfUpgrades]upgrade
|
|||
|
||||
var UnsupportedDatabaseVersion = fmt.Errorf("unsupported database version")
|
||||
|
||||
func getVersion(dialect Dialect, db *sql.DB) (int, error) {
|
||||
func GetVersion(db *sql.DB) (int, error) {
|
||||
_, err := db.Exec("CREATE TABLE IF NOT EXISTS version (version INTEGER)")
|
||||
if err != nil {
|
||||
return -1, err
|
||||
|
@ -42,7 +48,7 @@ func getVersion(dialect Dialect, db *sql.DB) (int, error) {
|
|||
return version, nil
|
||||
}
|
||||
|
||||
func setVersion(dialect Dialect, tx *sql.Tx, version int) error {
|
||||
func SetVersion(tx *sql.Tx, version int) error {
|
||||
_, err := tx.Exec("DELETE FROM version")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -62,7 +68,7 @@ func Run(log log.Logger, dialectName string, db *sql.DB) error {
|
|||
return fmt.Errorf("unknown dialect %s", dialectName)
|
||||
}
|
||||
|
||||
version, err := getVersion(dialect, db)
|
||||
version, err := GetVersion(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -78,11 +84,11 @@ func Run(log log.Logger, dialectName string, db *sql.DB) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = upgrade.fn(dialect, tx, db)
|
||||
err = upgrade.fn(tx, context{dialect, db, log})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = setVersion(dialect, tx, version+i+1)
|
||||
err = SetVersion(tx, version+i+1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
9
main.go
9
main.go
|
@ -164,6 +164,15 @@ func (bridge *Bridge) Init() {
|
|||
os.Exit(14)
|
||||
}
|
||||
|
||||
if len(bridge.Config.AppService.StateStore) > 0 && bridge.Config.AppService.StateStore != "./mx-state.json" {
|
||||
version, err := upgrades.GetVersion(bridge.DB.DB)
|
||||
if version < 0 && err == nil {
|
||||
bridge.Log.Fatalln("Non-standard state store path. Please move the state store to ./mx-state.json " +
|
||||
"and update the config. The state store will be migrated into the db on the next launch.")
|
||||
os.Exit(18)
|
||||
}
|
||||
}
|
||||
|
||||
bridge.Log.Debugln("Initializing state store")
|
||||
bridge.StateStore = database.NewSQLStateStore(bridge.DB)
|
||||
bridge.AS.StateStore = bridge.StateStore
|
||||
|
|
Loading…
Reference in a new issue