* feat(codex): support custom base URL * fix(codex): require HTTPS for custom base URL * docs: document changed subscription functions * fix(groups): 展示并区分详情中的默认与自定义地址 * fix(groups): 统一上游地址配置交互与图标位置 * fix(subscription): 绑定额度重置操作的上游地址 * fix(gateway): 隔离旧上游请求的健康状态更新 --------- Co-authored-by: tbphp <tangb7420@gmail.com>
52 lines
1.9 KiB
Go
52 lines
1.9 KiB
Go
package control
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"gpt-load/internal/channel"
|
|
"gpt-load/internal/storage/models"
|
|
subscriptionruntime "gpt-load/internal/subscription/runtime"
|
|
)
|
|
|
|
func sameSubscriptionTarget(before, after models.Group) bool {
|
|
return before.ID == after.ID && before.ChannelID == after.ChannelID &&
|
|
before.ConnectionType == after.ConnectionType && bytes.Equal(bytes.TrimSpace(before.Params), bytes.TrimSpace(after.Params))
|
|
}
|
|
|
|
func (s *Service) restoreCredentialRuntimeForTarget(ctx context.Context, group models.Group, credentialID uint) (bool, bool, error) {
|
|
// 上游已确认消耗成功,客户端取消不能中断本地收尾。
|
|
finalizeContext, cancel := context.WithTimeout(context.WithoutCancel(ctx), controlTransactionCleanupTimeout)
|
|
defer cancel()
|
|
s.writeMu.RLock()
|
|
defer s.writeMu.RUnlock()
|
|
current, err := loadGroupRow(s.db.WithContext(finalizeContext), group.ID)
|
|
if err != nil {
|
|
return false, false, err
|
|
}
|
|
if !sameSubscriptionTarget(group, current) {
|
|
return false, false, nil
|
|
}
|
|
return s.restoreCredentialRuntimeAfterReset(credentialID), true, nil
|
|
}
|
|
|
|
// resolveSubscriptionTarget validates stored channel parameters and freezes
|
|
// their resolved provider configuration for one subscription operation.
|
|
func (s *Service) resolveSubscriptionTarget(
|
|
channelID channel.ID,
|
|
params []byte,
|
|
) (subscriptionruntime.Target, error) {
|
|
resolved, err := s.channelRegistry.Resolve(channelID, json.RawMessage(params))
|
|
if err != nil {
|
|
return subscriptionruntime.Target{}, err
|
|
}
|
|
return subscriptionruntime.NewTarget(resolved.TargetConfig), nil
|
|
}
|
|
|
|
// subscriptionTargetFromResolved copies a previously validated channel target
|
|
// into the provider-neutral subscription runtime representation.
|
|
func subscriptionTargetFromResolved(resolved channel.ResolvedTarget) subscriptionruntime.Target {
|
|
return subscriptionruntime.NewTarget(resolved.TargetConfig)
|
|
}
|