fix: resolve P1 backend consistency issues
This commit is contained in:
@@ -167,6 +167,10 @@ func ensureIMGroupBusinessTables(exec sqlExecutor) error {
|
||||
PRIMARY KEY(id), UNIQUE INDEX uk_im_group_events_outbox_event(event_id),
|
||||
INDEX idx_im_group_events_outbox_pending(status, next_retry_at, id), INDEX idx_im_group_events_outbox_topic(topic, id DESC)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci`,
|
||||
`UPDATE im_topics SET public=JSON_SET(public, '$.fn', JSON_UNQUOTE(JSON_EXTRACT(public, '$.name')))
|
||||
WHERE name LIKE 'grp%' AND JSON_VALID(public)
|
||||
AND COALESCE(JSON_UNQUOTE(JSON_EXTRACT(public, '$.fn')), '') = ''
|
||||
AND COALESCE(JSON_UNQUOTE(JSON_EXTRACT(public, '$.name')), '') <> ''`,
|
||||
}
|
||||
for _, statement := range statements {
|
||||
if _, err := exec.Exec(statement); err != nil {
|
||||
|
||||
@@ -22,8 +22,8 @@ func TestEnsureIMGroupBusinessTablesUsesSelectedTenantDatabase(t *testing.T) {
|
||||
if err := ensureIMGroupBusinessTables(exec); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(exec.statements) != 13 {
|
||||
t.Fatalf("created %d group tables, want 13", len(exec.statements))
|
||||
if len(exec.statements) != 14 {
|
||||
t.Fatalf("executed %d group schema statements, want 14", len(exec.statements))
|
||||
}
|
||||
for _, statement := range exec.statements {
|
||||
if strings.Contains(strings.ToLower(statement), "tinode.") || strings.Contains(strings.ToLower(statement), "create database") {
|
||||
@@ -40,4 +40,7 @@ func TestEnsureIMGroupBusinessTablesUsesSelectedTenantDatabase(t *testing.T) {
|
||||
t.Fatalf("group schema is missing snowflake primary-key definition %q", expected)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(joined, "json_set(public, '$.fn'") {
|
||||
t.Fatal("group schema is missing historical public.fn backfill")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7051,15 +7051,17 @@ func (a *adapter) TenantTopicDraftPut(id t.TenantID, uid t.Uid, topic, content s
|
||||
return nil, err
|
||||
}
|
||||
now := t.TimeNow()
|
||||
_, err = a.db.ExecContext(ctx, `INSERT INTO im_topic_drafts
|
||||
res, err := a.db.ExecContext(ctx, `INSERT INTO im_topic_drafts
|
||||
(id,user_id,topic,content,entities_json,version,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?)
|
||||
ON DUPLICATE KEY UPDATE content=VALUES(content),entities_json=VALUES(entities_json),
|
||||
version=version+1,updated_at=VALUES(updated_at)`,
|
||||
ON DUPLICATE KEY UPDATE id=id`,
|
||||
draftID, decodeUID(uid), strings.TrimSpace(topic), content, entities, 1, now, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if affected, _ := res.RowsAffected(); affected == 0 {
|
||||
return nil, t.ErrInvalidResponse
|
||||
}
|
||||
return a.topicDraftByKey(ctx, uid, strings.TrimSpace(topic))
|
||||
}
|
||||
res, err := a.db.ExecContext(ctx, `UPDATE im_topic_drafts
|
||||
@@ -9210,6 +9212,13 @@ func (a *adapter) TenantFriendRequestAccept(id t.TenantID, requestID string, act
|
||||
row.HandledAt = &handledAt
|
||||
row.UpdatedAt = handledAt
|
||||
}
|
||||
if _, err = tx.ExecContext(ctx, `UPDATE im_friend_requests SET status=?,handled_at=?,updated_at=?
|
||||
WHERE request_id<>? AND status=? AND
|
||||
((applicant_id=? AND target_id=?) OR (applicant_id=? AND target_id=?))`,
|
||||
t.FriendRequestExpired, handledAt, handledAt, requestID, t.FriendRequestPending,
|
||||
decodeUID(applicant), decodeUID(target), decodeUID(target), decodeUID(applicant)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, pair := range [][2]t.Uid{{applicant, target}, {target, applicant}} {
|
||||
friendshipID, idErr := nextSnowflakeID()
|
||||
if idErr != nil {
|
||||
|
||||
@@ -936,11 +936,16 @@ func (a *adapter) TenantGroupFileCreate(id t.TenantID, file *t.GroupFile) (*t.Gr
|
||||
}
|
||||
a.enrichGroupFileFromUpload(id, file)
|
||||
now := t.TimeNow()
|
||||
ctx, cancel := a.getContext()
|
||||
ctx, cancel := a.getContextForTx()
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
_, err := a.db.ExecContext(ctx, `INSERT INTO im_group_files
|
||||
tx, err := a.db.BeginTxx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO im_group_files
|
||||
(group_file_id,topic,file_id,source_topic,source_seq,uploader_id,file_name,mime_type,file_type,file_size,status,idempotency_key,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
@@ -954,6 +959,29 @@ func (a *adapter) TenantGroupFileCreate(id t.TenantID, file *t.GroupFile) (*t.Gr
|
||||
if err != nil && !isDupe(err) {
|
||||
return nil, err
|
||||
}
|
||||
uploadID := strings.TrimSpace(file.FileID)
|
||||
if dot := strings.IndexByte(uploadID, '.'); dot > 0 {
|
||||
uploadID = uploadID[:dot]
|
||||
}
|
||||
if fid := t.ParseUid(uploadID); !fid.IsZero() {
|
||||
if a.tenantScopedDB {
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO im_filemsglinks(createdat,fileid,topic)
|
||||
SELECT ?,?,? WHERE NOT EXISTS (
|
||||
SELECT 1 FROM im_filemsglinks WHERE fileid=? AND topic=?)`,
|
||||
now, decodeUID(fid), file.Topic, decodeUID(fid), file.Topic)
|
||||
} else {
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO im_filemsglinks(tenant_id,createdat,fileid,topic)
|
||||
SELECT ?,?,?,? WHERE NOT EXISTS (
|
||||
SELECT 1 FROM im_filemsglinks WHERE tenant_id=? AND fileid=? AND topic=?)`,
|
||||
id, now, decodeUID(fid), file.Topic, id, decodeUID(fid), file.Topic)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err = tx.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
created, err := a.groupFileByQuery(ctx, "SELECT * FROM im_group_files WHERE topic=? AND file_id=?", file.Topic, file.FileID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user