|
|
@@ -5,6 +5,7 @@ import (
|
|
|
"fmt"
|
|
|
"one-api/common"
|
|
|
"strings"
|
|
|
+ "sync"
|
|
|
|
|
|
"github.com/samber/lo"
|
|
|
"gorm.io/gorm"
|
|
|
@@ -272,74 +273,45 @@ func UpdateAbilityByTag(tag string, newTag *string, priority *int64, weight *uin
|
|
|
return DB.Model(&Ability{}).Where("tag = ?", tag).Updates(ability).Error
|
|
|
}
|
|
|
|
|
|
-func FixAbility() (int, error) {
|
|
|
- var channelIds []int
|
|
|
- count := 0
|
|
|
- // Find all channel ids from channel table
|
|
|
- err := DB.Model(&Channel{}).Pluck("id", &channelIds).Error
|
|
|
- if err != nil {
|
|
|
- common.SysError(fmt.Sprintf("Get channel ids from channel table failed: %s", err.Error()))
|
|
|
- return 0, err
|
|
|
- }
|
|
|
+var fixLock = sync.Mutex{}
|
|
|
|
|
|
- // Delete abilities of channels that are not in channel table - in batches to avoid too many placeholders
|
|
|
- if len(channelIds) > 0 {
|
|
|
- // Process deletion in chunks to avoid "too many placeholders" error
|
|
|
- for _, chunk := range lo.Chunk(channelIds, 100) {
|
|
|
- err = DB.Where("channel_id NOT IN (?)", chunk).Delete(&Ability{}).Error
|
|
|
- if err != nil {
|
|
|
- common.SysError(fmt.Sprintf("Delete abilities of channels (batch) that are not in channel table failed: %s", err.Error()))
|
|
|
- return 0, err
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // If no channels exist, delete all abilities
|
|
|
- err = DB.Delete(&Ability{}).Error
|
|
|
- if err != nil {
|
|
|
- common.SysError(fmt.Sprintf("Delete all abilities failed: %s", err.Error()))
|
|
|
- return 0, err
|
|
|
- }
|
|
|
- common.SysLog("Delete all abilities successfully")
|
|
|
- return 0, nil
|
|
|
+func FixAbility() (int, int, error) {
|
|
|
+ lock := fixLock.TryLock()
|
|
|
+ if !lock {
|
|
|
+ return 0, 0, errors.New("已经有一个修复任务在运行中,请稍后再试")
|
|
|
}
|
|
|
-
|
|
|
- common.SysLog(fmt.Sprintf("Delete abilities of channels that are not in channel table successfully, ids: %v", channelIds))
|
|
|
- count += len(channelIds)
|
|
|
-
|
|
|
- // Use channelIds to find channel not in abilities table
|
|
|
- var abilityChannelIds []int
|
|
|
- err = DB.Table("abilities").Distinct("channel_id").Pluck("channel_id", &abilityChannelIds).Error
|
|
|
+ defer fixLock.Unlock()
|
|
|
+ var channels []*Channel
|
|
|
+ // Find all channels
|
|
|
+ err := DB.Model(&Channel{}).Find(&channels).Error
|
|
|
if err != nil {
|
|
|
- common.SysError(fmt.Sprintf("Get channel ids from abilities table failed: %s", err.Error()))
|
|
|
- return count, err
|
|
|
+ return 0, 0, err
|
|
|
}
|
|
|
-
|
|
|
- var channels []Channel
|
|
|
- if len(abilityChannelIds) == 0 {
|
|
|
- err = DB.Find(&channels).Error
|
|
|
- } else {
|
|
|
- // Process query in chunks to avoid "too many placeholders" error
|
|
|
- err = nil
|
|
|
- for _, chunk := range lo.Chunk(abilityChannelIds, 100) {
|
|
|
- var channelsChunk []Channel
|
|
|
- err = DB.Where("id NOT IN (?)", chunk).Find(&channelsChunk).Error
|
|
|
- if err != nil {
|
|
|
- common.SysError(fmt.Sprintf("Find channels not in abilities table failed: %s", err.Error()))
|
|
|
- return count, err
|
|
|
- }
|
|
|
- channels = append(channels, channelsChunk...)
|
|
|
- }
|
|
|
+ if len(channels) == 0 {
|
|
|
+ return 0, 0, nil
|
|
|
}
|
|
|
-
|
|
|
- for _, channel := range channels {
|
|
|
- err := channel.UpdateAbilities(nil)
|
|
|
+ successCount := 0
|
|
|
+ failCount := 0
|
|
|
+ for _, chunk := range lo.Chunk(channels, 50) {
|
|
|
+ ids := lo.Map(chunk, func(c *Channel, _ int) int { return c.Id })
|
|
|
+ // Delete all abilities of this channel
|
|
|
+ err = DB.Where("channel_id IN ?", ids).Delete(&Ability{}).Error
|
|
|
if err != nil {
|
|
|
- common.SysError(fmt.Sprintf("Update abilities of channel %d failed: %s", channel.Id, err.Error()))
|
|
|
- } else {
|
|
|
- common.SysLog(fmt.Sprintf("Update abilities of channel %d successfully", channel.Id))
|
|
|
- count++
|
|
|
+ common.SysError(fmt.Sprintf("Delete abilities failed: %s", err.Error()))
|
|
|
+ failCount += len(chunk)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // Then add new abilities
|
|
|
+ for _, channel := range chunk {
|
|
|
+ err = channel.AddAbilities()
|
|
|
+ if err != nil {
|
|
|
+ common.SysError(fmt.Sprintf("Add abilities for channel %d failed: %s", channel.Id, err.Error()))
|
|
|
+ failCount++
|
|
|
+ } else {
|
|
|
+ successCount++
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
InitChannelCache()
|
|
|
- return count, nil
|
|
|
+ return successCount, failCount, nil
|
|
|
}
|