yumi-golang/internal/service/gameking/archive_safety.go
2026-07-18 19:38:00 +08:00

72 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package gameking
import (
"errors"
"net/http"
"strings"
"chatapp3-golang/internal/model"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// ensureActivityEnableSafetyTx 把“索引已在线”和“GC 没在删除”纳入首次启用事务。
// 它与 GC 删除事务锁同一控制行,因此两个并发请求不会同时各自通过旧状态检查。
func ensureActivityEnableSafetyTx(tx *gorm.DB) error {
if err := requireBackfillIndexOnDB(tx); err != nil {
return err
}
var run model.TaskCenterArchiveGCRun
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", uint8(1)).First(&run).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return NewAppError(http.StatusServiceUnavailable, "archive_gc_migration_required", "migration 060 archive GC safety state is required before enabling game king")
}
return NewAppError(http.StatusServiceUnavailable, "archive_gc_state_check_failed", "cannot verify archive GC state before enabling game king")
}
if strings.EqualFold(run.Status, "RUNNING") {
return NewAppError(http.StatusConflict, "archive_gc_running", "pause task center archive GC before enabling game king")
}
return nil
}
func requireBackfillIndexOnDB(db *gorm.DB) error {
var columns []backfillIndexColumn
if err := db.Raw(`
-- 与任务中心 GC 门禁保持相同映射规则;不加别名时 MySQL 的大写列标签不会填充
-- 显式小写 GORM tag导致真实存在的 Game King 索引也被误判为缺失。
SELECT COLUMN_NAME AS column_name,
SEQ_IN_INDEX AS seq_in_index,
SUB_PART AS sub_part,
INDEX_TYPE AS index_type,
IS_VISIBLE AS is_visible
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'task_center_event_archive_outbox'
AND INDEX_NAME = ?
ORDER BY SEQ_IN_INDEX ASC`, taskCenterGameKingBackfillIndex).Scan(&columns).Error; err != nil {
return NewAppError(http.StatusServiceUnavailable, "backfill_index_check_failed", "cannot verify the required task center backfill index")
}
required := [...]string{"sys_origin", "event_type", "occurred_at", "id"}
if len(columns) == len(required) {
valid := true
for index, requiredName := range required {
column := columns[index]
if column.SeqInIndex != index+1 || !strings.EqualFold(column.ColumnName, requiredName) || column.SubPart != nil ||
!strings.EqualFold(column.IndexType, "BTREE") || !strings.EqualFold(column.IsVisible, "YES") {
valid = false
break
}
}
if valid {
return nil
}
}
return NewAppError(
http.StatusServiceUnavailable,
"backfill_index_required",
"migration 058 backfill index (sys_origin,event_type,occurred_at,id) must be online before enabling or backfill",
)
}