chore: prepare 0.1.127 release
This commit is contained in:
@@ -1 +1 @@
|
||||
0.1.126
|
||||
0.1.127
|
||||
|
||||
@@ -76,22 +76,6 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if setup is needed
|
||||
if setup.NeedsSetup() {
|
||||
// Check if auto-setup is enabled (for Docker deployment)
|
||||
if setup.AutoSetupEnabled() {
|
||||
log.Println("Auto setup mode enabled...")
|
||||
if err := setup.AutoSetupFromEnv(); err != nil {
|
||||
log.Fatalf("Auto setup failed: %v", err)
|
||||
}
|
||||
// Continue to main server after auto-setup
|
||||
} else {
|
||||
log.Println("First run detected, starting setup wizard...")
|
||||
runSetupServer()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Normal server mode
|
||||
runMainServer()
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
|
||||
updateCache := repository.NewUpdateCache(redisClient)
|
||||
gitHubReleaseClient := repository.ProvideGitHubReleaseClient(configConfig)
|
||||
serviceBuildInfo := provideServiceBuildInfo(buildInfo)
|
||||
updateService := service.ProvideUpdateService(updateCache, gitHubReleaseClient, serviceBuildInfo)
|
||||
updateService := service.ProvideUpdateService(updateCache, gitHubReleaseClient, serviceBuildInfo, configConfig)
|
||||
idempotencyRepository := repository.NewIdempotencyRepository(client, db)
|
||||
systemOperationLockService := service.ProvideSystemOperationLockService(idempotencyRepository, configConfig)
|
||||
systemHandler := handler.ProvideSystemHandler(updateService, systemOperationLockService)
|
||||
|
||||
@@ -148,6 +148,8 @@ type GeminiTierQuotaConfig struct {
|
||||
}
|
||||
|
||||
type UpdateConfig struct {
|
||||
// GitHubRepo 用于在线更新的 GitHub 仓库,格式 owner/repo
|
||||
GitHubRepo string `mapstructure:"github_repo"`
|
||||
// ProxyURL 用于访问 GitHub 的代理地址
|
||||
// 支持 http/https/socks5/socks5h 协议
|
||||
// 例如: "http://127.0.0.1:7890", "socks5://127.0.0.1:1080"
|
||||
@@ -988,6 +990,8 @@ type DatabaseConfig struct {
|
||||
Password string `mapstructure:"password"`
|
||||
DBName string `mapstructure:"dbname"`
|
||||
SSLMode string `mapstructure:"sslmode"`
|
||||
// AutoMigrate controls whether startup applies embedded SQL migrations.
|
||||
AutoMigrate bool `mapstructure:"auto_migrate"`
|
||||
// 连接池配置(性能优化:可配置化连接池参数)
|
||||
// MaxOpenConns: 最大打开连接数,控制数据库连接上限,防止资源耗尽
|
||||
MaxOpenConns int `mapstructure:"max_open_conns"`
|
||||
@@ -1543,6 +1547,7 @@ func setDefaults() {
|
||||
viper.SetDefault("database.password", "postgres")
|
||||
viper.SetDefault("database.dbname", "sub2api")
|
||||
viper.SetDefault("database.sslmode", "prefer")
|
||||
viper.SetDefault("database.auto_migrate", true)
|
||||
viper.SetDefault("database.max_open_conns", 256)
|
||||
viper.SetDefault("database.max_idle_conns", 128)
|
||||
viper.SetDefault("database.conn_max_lifetime_minutes", 30)
|
||||
@@ -1606,6 +1611,10 @@ func setDefaults() {
|
||||
viper.SetDefault("pricing.update_interval_hours", 24)
|
||||
viper.SetDefault("pricing.hash_check_interval_minutes", 10)
|
||||
|
||||
// Update
|
||||
viper.SetDefault("update.github_repo", "man209111-cpu/sub2api")
|
||||
viper.SetDefault("update.proxy_url", "")
|
||||
|
||||
// Timezone (default to Asia/Shanghai for Chinese users)
|
||||
viper.SetDefault("timezone", "Asia/Shanghai")
|
||||
|
||||
|
||||
@@ -54,14 +54,14 @@ func InitEnt(cfg *config.Config) (*ent.Client, *sql.DB, error) {
|
||||
}
|
||||
applyDBPoolSettings(drv.DB(), cfg)
|
||||
|
||||
// 确保数据库 schema 已准备就绪。
|
||||
// SQL 迁移文件是 schema 的权威来源(source of truth)。
|
||||
// 这种方式比 Ent 的自动迁移更可控,支持复杂的迁移场景。
|
||||
migrationCtx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
defer cancel()
|
||||
if err := applyMigrationsFS(migrationCtx, drv.DB(), migrations.FS); err != nil {
|
||||
_ = drv.Close() // 迁移失败时关闭驱动,避免资源泄露
|
||||
return nil, nil, err
|
||||
if cfg.Database.AutoMigrate {
|
||||
// SQL migration files are the source of truth for schema changes.
|
||||
if err := applyMigrationsFS(migrationCtx, drv.DB(), migrations.FS); err != nil {
|
||||
_ = drv.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// 创建 Ent 客户端,绑定到已配置的数据库驱动。
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
updateCacheKey = "update_check_cache"
|
||||
updateCacheTTL = 1200 // 20 minutes
|
||||
githubRepo = "Wei-Shaw/sub2api"
|
||||
updateCacheKey = "update_check_cache"
|
||||
updateCacheTTL = 1200 // 20 minutes
|
||||
defaultGitHubRepo = "man209111-cpu/sub2api"
|
||||
|
||||
// Security: allowed download domains for updates
|
||||
allowedDownloadHost = "github.com"
|
||||
@@ -51,15 +51,21 @@ type UpdateService struct {
|
||||
githubClient GitHubReleaseClient
|
||||
currentVersion string
|
||||
buildType string // "source" for manual builds, "release" for CI builds
|
||||
githubRepo string
|
||||
}
|
||||
|
||||
// NewUpdateService creates a new UpdateService
|
||||
func NewUpdateService(cache UpdateCache, githubClient GitHubReleaseClient, version, buildType string) *UpdateService {
|
||||
func NewUpdateService(cache UpdateCache, githubClient GitHubReleaseClient, version, buildType, githubRepo string) *UpdateService {
|
||||
githubRepo = strings.TrimSpace(githubRepo)
|
||||
if githubRepo == "" {
|
||||
githubRepo = defaultGitHubRepo
|
||||
}
|
||||
return &UpdateService{
|
||||
cache: cache,
|
||||
githubClient: githubClient,
|
||||
currentVersion: version,
|
||||
buildType: buildType,
|
||||
githubRepo: githubRepo,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +78,7 @@ type UpdateInfo struct {
|
||||
Cached bool `json:"cached"`
|
||||
Warning string `json:"warning,omitempty"`
|
||||
BuildType string `json:"build_type"` // "source" or "release"
|
||||
GitHubRepo string `json:"github_repo"`
|
||||
}
|
||||
|
||||
// ReleaseInfo contains GitHub release details
|
||||
@@ -129,6 +136,7 @@ func (s *UpdateService) CheckUpdate(ctx context.Context, force bool) (*UpdateInf
|
||||
HasUpdate: false,
|
||||
Warning: err.Error(),
|
||||
BuildType: s.buildType,
|
||||
GitHubRepo: s.githubRepo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -274,7 +282,7 @@ func (s *UpdateService) Rollback() error {
|
||||
}
|
||||
|
||||
func (s *UpdateService) fetchLatestRelease(ctx context.Context) (*UpdateInfo, error) {
|
||||
release, err := s.githubClient.FetchLatestRelease(ctx, githubRepo)
|
||||
release, err := s.githubClient.FetchLatestRelease(ctx, s.githubRepo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -301,8 +309,9 @@ func (s *UpdateService) fetchLatestRelease(ctx context.Context) (*UpdateInfo, er
|
||||
HTMLURL: release.HTMLURL,
|
||||
Assets: assets,
|
||||
},
|
||||
Cached: false,
|
||||
BuildType: s.buildType,
|
||||
Cached: false,
|
||||
BuildType: s.buildType,
|
||||
GitHubRepo: s.githubRepo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -477,11 +486,16 @@ func (s *UpdateService) getFromCache(ctx context.Context) (*UpdateInfo, error) {
|
||||
Latest string `json:"latest"`
|
||||
ReleaseInfo *ReleaseInfo `json:"release_info"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
GitHubRepo string `json:"github_repo"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), &cached); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strings.TrimSpace(cached.GitHubRepo) != s.githubRepo {
|
||||
return nil, fmt.Errorf("cache repo mismatch")
|
||||
}
|
||||
|
||||
if time.Now().Unix()-cached.Timestamp > updateCacheTTL {
|
||||
return nil, fmt.Errorf("cache expired")
|
||||
}
|
||||
@@ -493,6 +507,7 @@ func (s *UpdateService) getFromCache(ctx context.Context) (*UpdateInfo, error) {
|
||||
ReleaseInfo: cached.ReleaseInfo,
|
||||
Cached: true,
|
||||
BuildType: s.buildType,
|
||||
GitHubRepo: s.githubRepo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -501,10 +516,12 @@ func (s *UpdateService) saveToCache(ctx context.Context, info *UpdateInfo) {
|
||||
Latest string `json:"latest"`
|
||||
ReleaseInfo *ReleaseInfo `json:"release_info"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
GitHubRepo string `json:"github_repo"`
|
||||
}{
|
||||
Latest: info.LatestVersion,
|
||||
ReleaseInfo: info.ReleaseInfo,
|
||||
Timestamp: time.Now().Unix(),
|
||||
GitHubRepo: s.githubRepo,
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(cacheData)
|
||||
|
||||
@@ -31,8 +31,8 @@ func ProvidePricingService(cfg *config.Config, remoteClient PricingRemoteClient)
|
||||
}
|
||||
|
||||
// ProvideUpdateService creates UpdateService with BuildInfo
|
||||
func ProvideUpdateService(cache UpdateCache, githubClient GitHubReleaseClient, buildInfo BuildInfo) *UpdateService {
|
||||
return NewUpdateService(cache, githubClient, buildInfo.Version, buildInfo.BuildType)
|
||||
func ProvideUpdateService(cache UpdateCache, githubClient GitHubReleaseClient, buildInfo BuildInfo, cfg *config.Config) *UpdateService {
|
||||
return NewUpdateService(cache, githubClient, buildInfo.Version, buildInfo.BuildType, cfg.Update.GitHubRepo)
|
||||
}
|
||||
|
||||
// ProvideEmailQueueService creates EmailQueueService with default worker count
|
||||
|
||||
Reference in New Issue
Block a user