diff --git a/cmd/replicationprober/envhelpers.go b/cmd/replicationprober/envhelpers.go deleted file mode 100644 index da294ba..0000000 --- a/cmd/replicationprober/envhelpers.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "log" - "os" - "strconv" - "time" -) - -func getDurationEnv(name string, defaultValue time.Duration) time.Duration { - envDurationStr := os.Getenv(name) - if envDurationStr == "" { - return defaultValue - } - duration, err := time.ParseDuration(envDurationStr) - if err != nil { - log.Fatalf("Failed to parse %s: %v", name, err) - } - return duration -} - -func getFloatEnv(name string, defaultValue float64) float64 { - envFloatStr := os.Getenv(name) - if envFloatStr == "" { - return defaultValue - } - envFloat, err := strconv.ParseFloat(envFloatStr, 64) - if err != nil { - log.Fatalf("Failed to parse %s: %v", name, err) - } - return envFloat -} - -func getStrEnv(name string, defaultValue string) string { - envStr := os.Getenv(name) - if envStr == "" { - return defaultValue - } - return envStr -} - -func getRequiredStrEnv(name string) string { - envStr := os.Getenv(name) - if envStr == "" { - log.Fatalf("Missing required env variable %s", name) - } - return envStr -} - -func getBoolEnv(name string, defaultValue bool) bool { - envStr := os.Getenv(name) - if envStr == "" { - return defaultValue - } - envBool, err := strconv.ParseBool(envStr) - if err != nil { - log.Fatalf("Failed to parse %s: %v", name, err) - } - return envBool -} diff --git a/cmd/replicationprober/main.go b/cmd/replicationprober/main.go index 5562e2b..2896b69 100644 --- a/cmd/replicationprober/main.go +++ b/cmd/replicationprober/main.go @@ -8,11 +8,11 @@ import ( "fmt" "log" "net/http" - "os" "sync" "time" "github.com/InfluxCommunity/influxdb3-go/influxdb3" + "github.com/caarlos0/env/v9" "github.com/p2004a/spring-rapid-syncer/pkg/bunny" "github.com/p2004a/spring-rapid-syncer/pkg/sfcache" ) @@ -49,26 +49,55 @@ func getExpectedStorageRegions(ctx context.Context, bunnyClient *bunny.Client, s return regions, nil } +type config struct { + Bunny struct { + AccessKey string + StorageZone string + } `envPrefix:"BUNNY_"` + InfluxDb struct { + Url string + Token string + Database string + } `envPrefix:"INFLUXDB_"` + BaseUrl string `envDefault:"https://repos-cdn.beyondallreason.dev"` + MaxRegionDistanceKm float64 `envDefault:"400"` + StorageEdgeMapCacheDuration time.Duration `envDefault:"24h"` + VersionGzCacheDuration time.Duration `envDefault:"10s"` + RefreshReplicationCanaryPeriod time.Duration `envDefault:"5m"` + CheckReplicationStatusPeriod time.Duration `envDefault:"2m"` + CheckRedirectStatusPeriod time.Duration `envDefault:"2m"` + EnableStorageReplicationProber bool `envDefault:"true"` + EnableRedirectStatusProber bool `envDefault:"true"` + Port string `envDefault:"8080"` +} + func main() { - bunnyAccessKey := getRequiredStrEnv("BUNNY_ACCESS_KEY") - bunnyClient := bunny.NewClient(bunnyAccessKey) + cfg := config{} + if err := env.ParseWithOptions(&cfg, env.Options{ + RequiredIfNoDef: true, + UseFieldNameByDefault: true, + }); err != nil { + log.Fatalf("%+v\n", err) + + } + + bunnyClient := bunny.NewClient(cfg.Bunny.AccessKey) - bunnyStorageZone := getRequiredStrEnv("BUNNY_STORAGE_ZONE") ctx := context.Background() - bunnyStorageZoneClient, err := bunnyClient.NewStorageZoneClient(ctx, bunnyStorageZone) + bunnyStorageZoneClient, err := bunnyClient.NewStorageZoneClient(ctx, cfg.Bunny.StorageZone) if err != nil { log.Fatalf("Failed to create Bunny storage zone client: %v", err) } - expectedStorageRegions, err := getExpectedStorageRegions(ctx, bunnyClient, bunnyStorageZone) + expectedStorageRegions, err := getExpectedStorageRegions(ctx, bunnyClient, cfg.Bunny.StorageZone) if err != nil { log.Fatalf("Failed to get expected storage regions: %v", err) } influxdbClient, err := influxdb3.New(influxdb3.ClientConfig{ - Host: getRequiredStrEnv("INFLUXDB_URL"), - Token: getRequiredStrEnv("INFLUXDB_TOKEN"), - Database: getRequiredStrEnv("INFLUXDB_DATABASE"), + Host: cfg.InfluxDb.Url, + Token: cfg.InfluxDb.Token, + Database: cfg.InfluxDb.Database, }) if err != nil { log.Fatalf("Failed to create InfluxDB client: %v", err) @@ -80,17 +109,17 @@ func main() { }, bunny: bunnyClient, bunnyStorageZone: bunnyStorageZoneClient, - baseUrl: getStrEnv("BASE_URL", "https://repos-cdn.beyondallreason.dev"), - maxRegionDistanceKm: getFloatEnv("MAX_REGION_DISTANCE_KM", 400), + baseUrl: cfg.BaseUrl, + maxRegionDistanceKm: cfg.MaxRegionDistanceKm, expectedStorageRegions: expectedStorageRegions, storageEdgeMapCache: sfcache.Cache[StorageEdgeMap]{ - Timeout: getDurationEnv("STORAGE_EDGE_MAP_CACHE_DURATION", time.Hour*24), + Timeout: cfg.StorageEdgeMapCacheDuration, }, versionsGzCache: sfcache.Cache[[]*replicatedFile]{ - Timeout: getDurationEnv("VERSION_GZ_CACHE_DURATION", time.Second*10), + Timeout: cfg.VersionGzCacheDuration, }, - refreshReplicationCanaryPeriod: getDurationEnv("REFRESH_REPLICATION_CANARY_PERIOD", time.Minute*5), - checkReplicationStatusPeriod: getDurationEnv("CHECK_REPLICATION_STATUS_PERIOD", time.Minute*2), + refreshReplicationCanaryPeriod: cfg.RefreshReplicationCanaryPeriod, + checkReplicationStatusPeriod: cfg.CheckRedirectStatusPeriod, influxdbClient: influxdbClient, } @@ -98,7 +127,7 @@ func main() { http.HandleFunc("/replicationstatus_versionsgz", server.HandleReplicationStatusVersionsGz) http.HandleFunc("/replicationstatus", server.HandleReplicationStatus) - if getBoolEnv("ENABLE_STORAGE_REPLICATION_PROBER", true) { + if cfg.EnableStorageReplicationProber { go server.startCanaryUpdater(ctx) go server.startReplicationStatusChecker(ctx) } @@ -108,19 +137,14 @@ func main() { influxdbClient: influxdbClient, repo: versionsGzRepo, versionGzUrl: server.baseUrl + versionsGzFile, - probePeriod: getDurationEnv("CHECK_REDIRECT_STATUS_PERIOD", time.Minute*2), + probePeriod: cfg.CheckRedirectStatusPeriod, edgeServerRefreshPeriod: time.Hour * 1, } - if getBoolEnv("ENABLE_REDIRECT_STATUS_PROBER", true) { + if cfg.EnableRedirectStatusProber { go redirectProber.startProber(ctx) } - port := os.Getenv("PORT") - if port == "" { - port = "8080" - log.Printf("Defaulting to port %s", port) - } - if err := http.ListenAndServe(":"+port, nil); err != nil { + if err := http.ListenAndServe(":"+cfg.Port, nil); err != nil { log.Fatal(err) } } diff --git a/go.mod b/go.mod index d626b20..5a96a34 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/andybalholm/brotli v1.0.4 // indirect github.com/apache/arrow/go/v12 v12.0.1 // indirect github.com/apache/thrift v0.16.0 // indirect + github.com/caarlos0/env/v9 v9.0.0 // indirect github.com/goccy/go-json v0.9.11 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect diff --git a/go.sum b/go.sum index a78310c..51237f7 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/apache/arrow/go/v12 v12.0.1 h1:JsR2+hzYYjgSUkBSaahpqCetqZMr76djX80fF/ github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWMLpY67QwZ/WWw= github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/caarlos0/env/v9 v9.0.0 h1:SI6JNsOA+y5gj9njpgybykATIylrRMklbs5ch6wO6pc= +github.com/caarlos0/env/v9 v9.0.0/go.mod h1:ye5mlCVMYh6tZ+vCgrs/B95sj88cg5Tlnc0XIzgZ020= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=