Files
gpt-load/internal/channel/factory.go
2025-07-04 21:19:15 +08:00

85 lines
2.3 KiB
Go

package channel
import (
"encoding/json"
"fmt"
"gpt-load/internal/config"
"gpt-load/internal/models"
"net/http"
"net/url"
"time"
"gorm.io/datatypes"
)
// Factory is responsible for creating channel proxies.
type Factory struct {
settingsManager *config.SystemSettingsManager
}
// NewFactory creates a new channel factory.
func NewFactory(settingsManager *config.SystemSettingsManager) *Factory {
return &Factory{
settingsManager: settingsManager,
}
}
// GetChannel returns a channel proxy based on the group's channel type.
func (f *Factory) GetChannel(group *models.Group) (ChannelProxy, error) {
switch group.ChannelType {
case "openai":
return f.NewOpenAIChannel(group)
case "gemini":
return f.NewGeminiChannel(group)
default:
return nil, fmt.Errorf("unsupported channel type: %s", group.ChannelType)
}
}
// newBaseChannel is a helper function to create and configure a BaseChannel.
func (f *Factory) newBaseChannel(name string, upstreamsJSON datatypes.JSON, groupConfig datatypes.JSONMap) (*BaseChannel, error) {
type upstreamDef struct {
URL string `json:"url"`
Weight int `json:"weight"`
}
var defs []upstreamDef
if err := json.Unmarshal(upstreamsJSON, &defs); err != nil {
return nil, fmt.Errorf("failed to unmarshal upstreams for %s channel: %w", name, err)
}
if len(defs) == 0 {
return nil, fmt.Errorf("at least one upstream is required for %s channel", name)
}
var upstreamInfos []UpstreamInfo
for _, def := range defs {
u, err := url.Parse(def.URL)
if err != nil {
return nil, fmt.Errorf("failed to parse upstream url '%s' for %s channel: %w", def.URL, name, err)
}
weight := def.Weight
if weight <= 0 {
weight = 1 // Default weight to 1 if not specified or invalid
}
upstreamInfos = append(upstreamInfos, UpstreamInfo{URL: u, Weight: weight})
}
// Get effective settings by merging system and group configs
effectiveSettings := f.settingsManager.GetEffectiveConfig(groupConfig)
// Configure the HTTP client with the effective timeouts
httpClient := &http.Client{
Transport: &http.Transport{
IdleConnTimeout: time.Duration(effectiveSettings.IdleConnTimeout) * time.Second,
},
Timeout: time.Duration(effectiveSettings.RequestTimeout) * time.Second,
}
return &BaseChannel{
Name: name,
Upstreams: upstreamInfos,
HTTPClient: httpClient,
}, nil
}