Possibly significantly improve how portals are created and synced

This commit is contained in:
Tulir Asokan
2019-05-22 16:46:18 +03:00
parent 6f2a51410f
commit b363547bdf
10 changed files with 248 additions and 33 deletions

View File

@ -53,11 +53,23 @@ func (mq *MessageQuery) GetAll(chat PortalKey) (messages []*Message) {
}
func (mq *MessageQuery) GetByJID(chat PortalKey, jid types.WhatsAppMessageID) *Message {
return mq.get("SELECT * FROM message WHERE chat_jid=$1 AND chat_receiver=$2 AND jid=$3", chat.JID, chat.Receiver, jid)
return mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content " +
"FROM message WHERE chat_jid=$1 AND chat_receiver=$2 AND jid=$3", chat.JID, chat.Receiver, jid)
}
func (mq *MessageQuery) GetByMXID(mxid types.MatrixEventID) *Message {
return mq.get("SELECT * FROM message WHERE mxid=$1", mxid)
return mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content " +
"FROM message WHERE mxid=$1", mxid)
}
func (mq *MessageQuery) GetLastInChat(chat PortalKey) *Message {
msg := mq.get("SELECT chat_jid, chat_receiver, jid, mxid, sender, timestamp, content " +
"FROM message WHERE chat_jid=$1 AND chat_receiver=$2 ORDER BY timestamp DESC LIMIT 1", chat.JID, chat.Receiver)
if msg.Timestamp == 0 {
// Old db, we don't know what the last message is.
return nil
}
return msg
}
func (mq *MessageQuery) get(query string, args ...interface{}) *Message {
@ -72,16 +84,17 @@ type Message struct {
db *Database
log log.Logger
Chat PortalKey
JID types.WhatsAppMessageID
MXID types.MatrixEventID
Sender types.WhatsAppID
Content *waProto.Message
Chat PortalKey
JID types.WhatsAppMessageID
MXID types.MatrixEventID
Sender types.WhatsAppID
Timestamp uint64
Content *waProto.Message
}
func (msg *Message) Scan(row Scannable) *Message {
var content []byte
err := row.Scan(&msg.Chat.JID, &msg.Chat.Receiver, &msg.JID, &msg.MXID, &msg.Sender, &content)
err := row.Scan(&msg.Chat.JID, &msg.Chat.Receiver, &msg.JID, &msg.MXID, &msg.Sender, &msg.Timestamp, &content)
if err != nil {
if err != sql.ErrNoRows {
msg.log.Errorln("Database scan failed:", err)

View File

@ -0,0 +1,15 @@
package upgrades
import (
"database/sql"
)
func init() {
upgrades[2] = upgrade{"Add timestamp column to messages", func(dialect Dialect, tx *sql.Tx) error {
_, err := tx.Exec("ALTER TABLE message ADD COLUMN timestamp BIGINT NOT NULL DEFAULT 0")
if err != nil {
return err
}
return nil
}}
}

View File

@ -0,0 +1,15 @@
package upgrades
import (
"database/sql"
)
func init() {
upgrades[3] = upgrade{"Add last_connection column to users", func(dialect Dialect, tx *sql.Tx) error {
_, err := tx.Exec(`ALTER TABLE "user" ADD COLUMN last_connection BIGINT NOT NULL DEFAULT 0`)
if err != nil {
return err
}
return nil
}}
}

View File

@ -22,7 +22,7 @@ type upgrade struct {
fn upgradeFunc
}
var upgrades [2]upgrade
var upgrades [4]upgrade
func getVersion(dialect Dialect, db *sql.DB) (int, error) {
_, err := db.Exec("CREATE TABLE IF NOT EXISTS version (version INTEGER)")
@ -65,7 +65,7 @@ func Run(log log.Logger, dialectName string, db *sql.DB) error {
log.Infofln("Database currently on v%d, latest: v%d", version, len(upgrades))
for i, upgrade := range upgrades[version:] {
log.Infofln("Upgrading database to v%d: %s", i+1, upgrade.message)
log.Infofln("Upgrading database to v%d: %s", version+i+1, upgrade.message)
tx, err := db.Begin()
if err != nil {
return err
@ -74,7 +74,7 @@ func Run(log log.Logger, dialectName string, db *sql.DB) error {
if err != nil {
return err
}
err = setVersion(dialect, tx, i+1)
err = setVersion(dialect, tx, version+i+1)
if err != nil {
return err
}

View File

@ -19,6 +19,7 @@ package database
import (
"database/sql"
"strings"
"time"
"github.com/Rhymen/go-whatsapp"
@ -76,12 +77,14 @@ type User struct {
JID types.WhatsAppID
ManagementRoom types.MatrixRoomID
Session *whatsapp.Session
LastConnection uint64
}
func (user *User) Scan(row Scannable) *User {
var jid, clientID, clientToken, serverToken sql.NullString
var encKey, macKey []byte
err := row.Scan(&user.MXID, &jid, &user.ManagementRoom, &clientID, &clientToken, &serverToken, &encKey, &macKey)
err := row.Scan(&user.MXID, &jid, &user.ManagementRoom, &clientID, &clientToken, &serverToken, &encKey, &macKey,
&user.LastConnection)
if err != nil {
if err != sql.ErrNoRows {
user.log.Errorln("Database scan failed:", err)
@ -134,18 +137,28 @@ func (user *User) sessionUnptr() (sess whatsapp.Session) {
func (user *User) Insert() {
sess := user.sessionUnptr()
_, err := user.db.Exec(`INSERT INTO "user" VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, user.MXID, user.jidPtr(),
user.ManagementRoom,
_, err := user.db.Exec(`INSERT INTO "user" (mxid, jid, management_room, last_connection, client_id, client_token, server_token, enc_key, mac_key) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
user.MXID, user.jidPtr(),
user.ManagementRoom, user.LastConnection,
sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey)
if err != nil {
user.log.Warnfln("Failed to insert %s: %v", user.MXID, err)
}
}
func (user *User) UpdateLastConnection() {
user.LastConnection = uint64(time.Now().Unix())
_, err := user.db.Exec(`UPDATE "user" SET last_connection=$1 WHERE mxid=$2`,
user.LastConnection, user.MXID)
if err != nil {
user.log.Warnfln("Failed to update last connection ts: %v", err)
}
}
func (user *User) Update() {
sess := user.sessionUnptr()
_, err := user.db.Exec(`UPDATE "user" SET jid=$1, management_room=$2, client_id=$3, client_token=$4, server_token=$5, enc_key=$6, mac_key=$7 WHERE mxid=$8`,
user.jidPtr(), user.ManagementRoom,
_, err := user.db.Exec(`UPDATE "user" SET jid=$1, management_room=$2, last_connection=$3, client_id=$4, client_token=$5, server_token=$6, enc_key=$7, mac_key=$8 WHERE mxid=$9`,
user.jidPtr(), user.ManagementRoom, user.LastConnection,
sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey,
user.MXID)
if err != nil {