150 lines
4.3 KiB
Go
150 lines
4.3 KiB
Go
// Package container assembles the 2.0 dependency graph with dig.
|
|
package container
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"go.uber.org/dig"
|
|
"gorm.io/gorm"
|
|
|
|
"gpt-load/internal/app"
|
|
"gpt-load/internal/control"
|
|
"gpt-load/internal/dialect"
|
|
"gpt-load/internal/gateway"
|
|
"gpt-load/internal/health"
|
|
"gpt-load/internal/platform/config"
|
|
"gpt-load/internal/platform/encryption"
|
|
"gpt-load/internal/platform/httpclient"
|
|
"gpt-load/internal/platform/redact"
|
|
"gpt-load/internal/pricing"
|
|
"gpt-load/internal/ratelimit"
|
|
"gpt-load/internal/requestlog"
|
|
"gpt-load/internal/state"
|
|
stateloader "gpt-load/internal/state/loader"
|
|
"gpt-load/internal/storage"
|
|
"gpt-load/internal/telemetry"
|
|
"gpt-load/internal/webui"
|
|
)
|
|
|
|
// BuildContainer creates the 2.0 runtime foundation dependency graph.
|
|
func BuildContainer() (*dig.Container, error) {
|
|
dependencyContainer := dig.New()
|
|
|
|
providers := []any{
|
|
config.Load,
|
|
func(cfg *config.Config) (encryption.Service, error) {
|
|
return encryption.NewServiceWithKeyFile(cfg.EncryptionKey, cfg.DataDir)
|
|
},
|
|
func(cfg *config.Config) (*gorm.DB, error) {
|
|
return storage.OpenWithSource(cfg.DatabaseDSN, cfg.DatabaseMetadata.Source)
|
|
},
|
|
app.NewEngine,
|
|
webui.NewServer,
|
|
state.NewManager,
|
|
state.NewKeyRegistry,
|
|
control.NewPriceRuntime,
|
|
health.NewStatsStore,
|
|
health.NewMutationCoordinator,
|
|
ratelimit.NewAccessKeyRPM,
|
|
func(limiter *ratelimit.AccessKeyRPM) gateway.AccessKeyRPMLimiter {
|
|
return limiter
|
|
},
|
|
func(manager *state.Manager) requestlog.RetentionPolicyProvider {
|
|
return retentionSnapshotProvider{manager: manager}
|
|
},
|
|
func(runtime *control.PriceRuntime) requestlog.PriceTableProvider {
|
|
return priceRuntimeProvider{runtime: runtime}
|
|
},
|
|
requestlog.NewService,
|
|
func(service *requestlog.Service) telemetry.RequestLogSink {
|
|
return service
|
|
},
|
|
func(service *requestlog.Service) control.RequestLogReader {
|
|
return service
|
|
},
|
|
func(service *requestlog.Service) control.UsageStatReader {
|
|
return service
|
|
},
|
|
func(service *requestlog.Service) control.RequestLogStatsReader {
|
|
return service
|
|
},
|
|
func(service *requestlog.Service) control.RequestLogCleaner {
|
|
return service
|
|
},
|
|
func(service *requestlog.Service) app.RequestLogRuntime {
|
|
return service
|
|
},
|
|
control.NewRuntime,
|
|
func(runtime *control.Runtime) app.ControlRuntime { return runtime },
|
|
httpclient.NewHTTPClientManager,
|
|
redact.New,
|
|
func(manager *httpclient.HTTPClientManager) *http.Client {
|
|
return manager.GetClient(&httpclient.Config{
|
|
ConnectTimeout: 15 * time.Second,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 20,
|
|
ResponseHeaderTimeout: 120 * time.Second,
|
|
DisableCompression: true,
|
|
WriteBufferSize: 32 * 1024,
|
|
ReadBufferSize: 32 * 1024,
|
|
ForceAttemptHTTP2: true,
|
|
TLSHandshakeTimeout: 15 * time.Second,
|
|
ExpectContinueTimeout: time.Second,
|
|
})
|
|
},
|
|
dialect.NewOpenAI,
|
|
dialect.NewAnthropic,
|
|
dialect.NewGemini,
|
|
func(
|
|
openAI *dialect.OpenAI,
|
|
anthropic *dialect.Anthropic,
|
|
gemini *dialect.Gemini,
|
|
) dialect.Set {
|
|
return dialect.NewSet(openAI, anthropic, gemini)
|
|
},
|
|
gateway.NewForwarder,
|
|
func(forwarder *gateway.Forwarder) gateway.AttemptForwarder { return forwarder },
|
|
gateway.NewHandler,
|
|
control.NewService,
|
|
func(service *control.Service) app.StartupBootstrap { return service },
|
|
func(service *control.Service) app.StartupRecovery { return service },
|
|
control.NewServer,
|
|
func(db *gorm.DB, manager *state.Manager, registry *state.KeyRegistry) app.RuntimeStateLoader {
|
|
return stateloader.New(db, manager, registry)
|
|
},
|
|
app.NewApp,
|
|
}
|
|
|
|
for _, provider := range providers {
|
|
if err := dependencyContainer.Provide(provider); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if err := dependencyContainer.Invoke(func(
|
|
engine *gin.Engine,
|
|
gatewayHandler *gateway.Handler,
|
|
controlServer *control.Server,
|
|
webUIServer *webui.Server,
|
|
) {
|
|
gatewayHandler.RegisterRoutes(engine)
|
|
controlServer.RegisterRoutes(engine)
|
|
webUIServer.RegisterRoutes(engine)
|
|
webUIServer.RegisterFallback(engine, gatewayHandler.Handle)
|
|
}); err != nil {
|
|
return nil, fmt.Errorf("register HTTP routes: %w", err)
|
|
}
|
|
return dependencyContainer, nil
|
|
}
|
|
|
|
type priceRuntimeProvider struct {
|
|
runtime *control.PriceRuntime
|
|
}
|
|
|
|
func (provider priceRuntimeProvider) Load() *pricing.Table {
|
|
return provider.runtime.Load()
|
|
}
|