fix: resolve im backend issue list regressions

This commit is contained in:
richjohnrambo
2026-09-17 14:59:16 +08:00
parent 760de35e10
commit 50f8581667
13 changed files with 750 additions and 181 deletions
+73 -17
View File
@@ -1359,6 +1359,7 @@ func createIMUserProductTables(tx *sql.Tx) error {
profile_visibility VARCHAR(32) NOT NULL DEFAULT 'friends',
last_seen_visibility VARCHAR(32) NOT NULL DEFAULT 'friends',
read_receipts TINYINT NOT NULL DEFAULT 1,
friend_request_verification TINYINT NOT NULL DEFAULT 1,
group_invite_verification TINYINT NOT NULL DEFAULT 0,
version INT NOT NULL DEFAULT 1,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
@@ -4762,31 +4763,44 @@ func (a *adapter) FileDeleteUnused(olderThan time.Time, limit int) ([]string, er
if err != nil {
return nil, err
}
defer rows.Close()
var locations []string
var ids []any
type gcCandidate struct {
id int
location string
}
var candidates []gcCandidate
for rows.Next() {
var id int
var loc string
if err = rows.Scan(&id, &loc); err != nil {
break
}
candidates = append(candidates, gcCandidate{id: id, location: loc})
}
if err == nil {
err = rows.Err()
}
rows.Close()
if err != nil {
return nil, err
}
var locations []string
var ids []any
for _, candidate := range candidates {
var noteRefs int
fileID := store.EncodeUid(int64(id)).String()
fileID := store.EncodeUid(int64(candidate.id)).String()
if err = tx.QueryRow(`SELECT COUNT(*) FROM im_meeting_note_files WHERE file_id=? AND status=? LIMIT 1`, fileID, t.MeetingNoteFileStatusActive).Scan(&noteRefs); err != nil {
break
}
if noteRefs > 0 {
continue
}
if loc != "" {
locations = append(locations, loc)
if candidate.location != "" {
locations = append(locations, candidate.location)
}
ids = append(ids, id)
}
if err == nil {
err = rows.Err()
ids = append(ids, candidate.id)
}
if err != nil {
@@ -4900,7 +4914,24 @@ func (a *adapter) FileUserHasAccess(fid string, uid t.Uid) (bool, error) {
defer cancel()
}
var allowed int
err := a.db.GetContext(ctx, &allowed, `
buildQuery := func(includeRecorder bool) (string, []any) {
recorderClause := ""
if includeRecorder {
recorderClause = `
OR mtg.recorder_user_id=?`
}
args := []any{
store.DecodeUid(fileID), fileID.String32(), "%/" + fileID.String32(), t.UploadCompleted,
store.DecodeUid(uid), store.DecodeUid(uid), store.DecodeUid(uid), t.RelationshipFriend,
store.DecodeUid(uid), store.DecodeUid(uid), t.GroupMemberStatusActive, store.DecodeUid(uid), store.DecodeUid(uid),
store.DecodeUid(uid), fid, fid,
fid, t.MeetingStateCanceled, store.DecodeUid(uid),
}
if includeRecorder {
args = append(args, store.DecodeUid(uid))
}
args = append(args, store.DecodeUid(uid))
return `
SELECT COUNT(*) FROM im_fileuploads AS fu
WHERE (fu.id=? OR fu.location=? OR fu.location LIKE ?) AND fu.status=? AND (
fu.userid=?
@@ -4958,18 +4989,29 @@ func (a *adapter) FileUserHasAccess(fid string, uid t.Uid) (bool, error) {
AND mtg.end_at<=CURRENT_TIMESTAMP(3)
AND (
mtg.organizer_id=?
OR mtg.recorder_user_id=?
` + recorderClause + `
OR EXISTS (
SELECT 1 FROM im_meeting_participants AS mp
WHERE mp.meeting_id=mtg.meeting_id AND mp.user_id=?
)
)
)
) LIMIT 1`,
store.DecodeUid(fileID), fileID.String32(), "%/"+fileID.String32(), t.UploadCompleted, store.DecodeUid(uid), store.DecodeUid(uid), store.DecodeUid(uid), t.RelationshipFriend,
store.DecodeUid(uid), store.DecodeUid(uid), t.GroupMemberStatusActive, store.DecodeUid(uid), store.DecodeUid(uid),
store.DecodeUid(uid), fid, fid,
fid, t.MeetingStateCanceled, store.DecodeUid(uid), store.DecodeUid(uid), store.DecodeUid(uid))
) LIMIT 1`, args
}
includeRecorder := true
run := func() error {
query, args := buildQuery(includeRecorder)
return a.db.GetContext(ctx, &allowed, query, args...)
}
err := run()
if isUnknownColumn(err) && strings.Contains(strings.ToLower(err.Error()), "recorder_user_id") {
includeRecorder = false
err = run()
}
for attempt := 0; isRetryableMySQLReadErr(err) && attempt < 2; attempt++ {
time.Sleep(time.Duration(attempt+1) * 25 * time.Millisecond)
err = run()
}
if err != nil {
return false, err
}
@@ -5108,6 +5150,20 @@ func isIDOutOfRange(err error) bool {
return ok && myerr.Number == 1264 && strings.Contains(strings.ToLower(myerr.Message), "id")
}
func isRetryableMySQLReadErr(err error) bool {
if err == nil {
return false
}
var myerr *ms.MySQLError
if !errors.As(err, &myerr) {
return false
}
if myerr.Number == 1213 || myerr.Number == 1205 {
return true
}
return strings.EqualFold(string(myerr.SQLState[:]), "40001")
}
func isPXCStrictModeNamedLockError(err error) bool {
if err == nil {
return false