()
| 89 | } |
| 90 | |
| 91 | func (channel *Channel) GetNextEnabledKey() (string, int, *types.NewAPIError) { |
| 92 | // If not in multi-key mode, return the original key string directly. |
| 93 | if !channel.ChannelInfo.IsMultiKey { |
| 94 | return channel.Key, 0, nil |
| 95 | } |
| 96 | |
| 97 | // Obtain all keys (split by \n) |
| 98 | keys := channel.getKeys() |
| 99 | if len(keys) == 0 { |
| 100 | // No keys available, return error, should disable the channel |
| 101 | return "", 0, types.NewError(errors.New("no keys available"), types.ErrorCodeChannelNoAvailableKey) |
| 102 | } |
| 103 | |
| 104 | statusList := channel.ChannelInfo.MultiKeyStatusList |
| 105 | // helper to get key status, default to enabled when missing |
| 106 | getStatus := func(idx int) int { |
| 107 | if statusList == nil { |
| 108 | return common.ChannelStatusEnabled |
| 109 | } |
| 110 | if status, ok := statusList[idx]; ok { |
| 111 | return status |
| 112 | } |
| 113 | return common.ChannelStatusEnabled |
| 114 | } |
| 115 | |
| 116 | // Collect indexes of enabled keys |
| 117 | enabledIdx := make([]int, 0, len(keys)) |
| 118 | for i := range keys { |
| 119 | if getStatus(i) == common.ChannelStatusEnabled { |
| 120 | enabledIdx = append(enabledIdx, i) |
| 121 | } |
| 122 | } |
| 123 | // If no specific status list or none enabled, fall back to first key |
| 124 | if len(enabledIdx) == 0 { |
| 125 | return keys[0], 0, nil |
| 126 | } |
| 127 | |
| 128 | switch channel.ChannelInfo.MultiKeyMode { |
| 129 | case constant.MultiKeyModeRandom: |
| 130 | // Randomly pick one enabled key |
| 131 | selectedIdx := enabledIdx[rand.Intn(len(enabledIdx))] |
| 132 | return keys[selectedIdx], selectedIdx, nil |
| 133 | case constant.MultiKeyModePolling: |
| 134 | // Use channel-specific lock to ensure thread-safe polling |
| 135 | lock := getChannelPollingLock(channel.Id) |
| 136 | lock.Lock() |
| 137 | defer lock.Unlock() |
| 138 | |
| 139 | channelInfo, err := CacheGetChannelInfo(channel.Id) |
| 140 | if err != nil { |
| 141 | return "", 0, types.NewError(err, types.ErrorCodeGetChannelFailed) |
| 142 | } |
| 143 | //println("before polling index:", channel.ChannelInfo.MultiKeyPollingIndex) |
| 144 | defer func() { |
| 145 | if common.DebugEnabled { |
| 146 | println(fmt.Sprintf("channel %d polling index: %d", channel.Id, channel.ChannelInfo.MultiKeyPollingIndex)) |
| 147 | } |
| 148 | if !common.MemoryCacheEnabled { |
no test coverage detected