MCPcopy
hub / github.com/QuantumNous/new-api / GetNextEnabledKey

Method GetNextEnabledKey

model/channel.go:199–283  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

197}
198
199func (channel *Channel) GetNextEnabledKey() (string, int, *types.NewAPIError) {
200 // If not in multi-key mode, return the original key string directly.
201 if !channel.ChannelInfo.IsMultiKey {
202 return channel.Key, 0, nil
203 }
204
205 // Obtain all keys (split by \n)
206 keys := channel.GetKeys()
207 if len(keys) == 0 {
208 // No keys available, return error, should disable the channel
209 return "", 0, types.NewError(errors.New("no keys available"), types.ErrorCodeChannelNoAvailableKey)
210 }
211
212 lock := GetChannelPollingLock(channel.Id)
213 lock.Lock()
214 defer lock.Unlock()
215
216 statusList := channel.ChannelInfo.MultiKeyStatusList
217 // helper to get key status, default to enabled when missing
218 getStatus := func(idx int) int {
219 if statusList == nil {
220 return common.ChannelStatusEnabled
221 }
222 if status, ok := statusList[idx]; ok {
223 return status
224 }
225 return common.ChannelStatusEnabled
226 }
227
228 // Collect indexes of enabled keys
229 enabledIdx := make([]int, 0, len(keys))
230 for i := range keys {
231 if getStatus(i) == common.ChannelStatusEnabled {
232 enabledIdx = append(enabledIdx, i)
233 }
234 }
235 // If no specific status list or none enabled, return an explicit error so caller can
236 // properly handle a channel with no available keys (e.g. mark channel disabled).
237 // Returning the first key here caused requests to keep using an already-disabled key.
238 if len(enabledIdx) == 0 {
239 return "", 0, types.NewError(errors.New("no enabled keys"), types.ErrorCodeChannelNoAvailableKey)
240 }
241
242 switch channel.ChannelInfo.MultiKeyMode {
243 case constant.MultiKeyModeRandom:
244 // Randomly pick one enabled key
245 selectedIdx := enabledIdx[rand.Intn(len(enabledIdx))]
246 return keys[selectedIdx], selectedIdx, nil
247 case constant.MultiKeyModePolling:
248 // Use channel-specific lock to ensure thread-safe polling
249
250 channelInfo, err := CacheGetChannelInfo(channel.Id)
251 if err != nil {
252 return "", 0, types.NewError(err, types.ErrorCodeGetChannelFailed, types.ErrOptionWithSkipRetry())
253 }
254 defer func() {
255 if common.DebugEnabled {
256 logger.LogDebug(nil, "channel %d polling index: %d", channel.Id, channel.ChannelInfo.MultiKeyPollingIndex)

Callers 4

FetchUpstreamRatiosFunction · 0.80
ResolveOriginTaskFunction · 0.80

Calls 9

GetKeysMethod · 0.95
SaveChannelInfoMethod · 0.95
NewErrorFunction · 0.92
ErrOptionWithSkipRetryFunction · 0.92
LogDebugFunction · 0.92
GetChannelPollingLockFunction · 0.85
getStatusFunction · 0.85
CacheGetChannelInfoFunction · 0.85
UnlockMethod · 0.80

Tested by

no test coverage detected