Sync profile source and message topic seq

This commit is contained in:
richjohnrambo
2026-09-04 16:06:57 +08:00
parent 47649d33e2
commit 7fb1ea70bc
5 changed files with 216 additions and 23 deletions
+82 -12
View File
@@ -1055,6 +1055,9 @@ func (a *adapter) UpgradeDb() error {
if err := a.ensureMessageTopicSeqIndex(); err != nil {
return err
}
if err := a.ensureTopicSeqMatchesMessages(); err != nil {
return err
}
if a.version == adpVersion {
return nil
@@ -1080,6 +1083,61 @@ func (a *adapter) ensureMessageTopicSeqIndex() error {
return err
}
func (a *adapter) ensureTopicSeqMatchesMessages() error {
ctx := context.Background()
conn, err := a.db.Connx(ctx)
if err != nil {
return err
}
defer conn.Close()
topicsScoped, err := identityColumnExists(ctx, conn, "im_topics", "tenant_id")
if err != nil {
return err
}
messagesScoped, err := identityColumnExists(ctx, conn, "im_messages", "tenant_id")
if err != nil {
return err
}
if topicsScoped && messagesScoped {
if _, err = conn.ExecContext(ctx, `UPDATE im_topics AS t
JOIN (SELECT tenant_id,topic,MAX(seqid) AS max_seq FROM im_messages GROUP BY tenant_id,topic) AS m
ON m.tenant_id=t.tenant_id AND m.topic COLLATE utf8mb4_unicode_ci=t.name
SET t.seqid=GREATEST(t.seqid,m.max_seq)
WHERE t.seqid<m.max_seq`); err != nil {
return err
}
} else {
if _, err = conn.ExecContext(ctx, `UPDATE im_topics AS t
JOIN (SELECT topic,MAX(seqid) AS max_seq FROM im_messages GROUP BY topic) AS m ON m.topic COLLATE utf8mb4_unicode_ci=t.name
SET t.seqid=GREATEST(t.seqid,m.max_seq)
WHERE t.seqid<m.max_seq`); err != nil {
return err
}
}
groupMessagesExist, err := identityTableExists(ctx, conn, "im_group_messages")
if err != nil || !groupMessagesExist {
return err
}
groupMessagesScoped, err := identityColumnExists(ctx, conn, "im_group_messages", "tenant_id")
if err != nil {
return err
}
if topicsScoped && groupMessagesScoped {
_, err = conn.ExecContext(ctx, `UPDATE im_topics AS t
JOIN (SELECT tenant_id,topic,MAX(seqid) AS max_seq FROM im_group_messages GROUP BY tenant_id,topic) AS m
ON m.tenant_id=t.tenant_id AND m.topic COLLATE utf8mb4_unicode_ci=t.name
SET t.seqid=GREATEST(t.seqid,m.max_seq)
WHERE t.seqid<m.max_seq`)
return err
}
_, err = conn.ExecContext(ctx, `UPDATE im_topics AS t
JOIN (SELECT topic,MAX(seqid) AS max_seq FROM im_group_messages GROUP BY topic) AS m ON m.topic COLLATE utf8mb4_unicode_ci=t.name
SET t.seqid=GREATEST(t.seqid,m.max_seq)
WHERE t.seqid<m.max_seq`)
return err
}
func createIMNotificationTables(tx *sql.Tx) error {
_, err := tx.Exec(
`CREATE TABLE im_system_notifications(
@@ -2019,6 +2077,10 @@ func (a *adapter) UserCreate(user *t.User) error {
if err != nil {
return err
}
profileID, err := nextSnowflakeID()
if err != nil {
return err
}
var phone any
if strings.TrimSpace(user.Phone) != "" {
canonicalPhone, err := normalizeUserPhone(user.Phone)
@@ -2048,6 +2110,11 @@ func (a *adapter) UserCreate(user *t.User) error {
securityID, decoded_uid, 1, user.CreatedAt, user.UpdatedAt); err != nil {
return err
}
nickname, avatarFileID := profileSeedFromPublic(user.Public)
if _, err = tx.Exec(`INSERT IGNORE INTO im_user_profiles(id,user_id,avatar_file_id,nickname,public_account,created_at,updated_at)
VALUES(?,?,?,?,?,?,?)`, profileID, decoded_uid, avatarFileID, nickname, user.Uid().UserId(), user.CreatedAt, user.UpdatedAt); err != nil {
return err
}
user.Tags = nil
return tx.Commit()
@@ -2316,13 +2383,15 @@ func (a *adapter) UserGet(uid t.Uid) (*t.User, error) {
if cancel != nil {
defer cancel()
}
var user t.User
err := a.db.GetContext(ctx, &user, `SELECT id,username,createdat,updatedat,state,stateat,access,lastseen,useragent,
COALESCE(phone,'') AS phone,public,trusted FROM im_users WHERE id=? AND state!=?`, store.DecodeUid(uid), t.StateDeleted)
var row profileUserRow
err := a.db.GetContext(ctx, &row, `SELECT u.id,u.username,u.createdat,u.updatedat,u.state,u.stateat,u.access,u.lastseen,u.useragent,
COALESCE(u.phone,'') AS phone,u.public,u.trusted,
p.nickname AS profile_nickname,p.avatar_file_id AS profile_avatar_file_id,p.updated_at AS profile_updated_at
FROM im_users AS u LEFT JOIN im_user_profiles AS p ON p.user_id=u.id
WHERE u.id=? AND u.state!=?`, store.DecodeUid(uid), t.StateDeleted)
if err == nil {
user := profileUserFromRow(row)
user.SetUid(uid)
user.Public = common.FromJSON(user.Public)
user.Trusted = common.FromJSON(user.Trusted)
return &user, nil
}
@@ -2348,8 +2417,11 @@ func (a *adapter) UserGetAll(ids ...t.Uid) ([]t.User, error) {
if cancel != nil {
defer cancel()
}
q, uids, _ := sqlx.In(`SELECT id,username,createdat,updatedat,state,stateat,access,lastseen,useragent,
COALESCE(phone,'') AS phone,public,trusted FROM im_users WHERE id IN (?) AND state!=?`, uids, t.StateDeleted)
q, uids, _ := sqlx.In(`SELECT u.id,u.username,u.createdat,u.updatedat,u.state,u.stateat,u.access,u.lastseen,u.useragent,
COALESCE(u.phone,'') AS phone,u.public,u.trusted,
p.nickname AS profile_nickname,p.avatar_file_id AS profile_avatar_file_id,p.updated_at AS profile_updated_at
FROM im_users AS u LEFT JOIN im_user_profiles AS p ON p.user_id=u.id
WHERE u.id IN (?) AND u.state!=?`, uids, t.StateDeleted)
rows, err := a.db.QueryxContext(ctx, a.db.Rebind(q), uids...)
if err != nil {
return nil, err
@@ -2357,14 +2429,12 @@ func (a *adapter) UserGetAll(ids ...t.Uid) ([]t.User, error) {
defer rows.Close()
for rows.Next() {
var user t.User
if err = rows.StructScan(&user); err != nil {
var row profileUserRow
if err = rows.StructScan(&row); err != nil {
users = nil
break
}
user.SetUid(common.EncodeUidString(user.Id))
user.Public = common.FromJSON(user.Public)
user.Trusted = common.FromJSON(user.Trusted)
user := profileUserFromRow(row)
users = append(users, user)
}