66 lines
2.4 KiB
Go
66 lines
2.4 KiB
Go
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(`
|
|
SELECT COLUMN_NAME, SEQ_IN_INDEX, SUB_PART, INDEX_TYPE, 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",
|
|
)
|
|
}
|