From 7db0d236c74b3147b60d0e175e5ea239a20c1fe9 Mon Sep 17 00:00:00 2001 From: matst80 Date: Sat, 27 Jun 2026 21:46:55 +0200 Subject: [PATCH] platform --- Dockerfile | 3 ++- cmd/backoffice/main.go | 14 ++++---------- cmd/cart/main.go | 16 ++++------------ cmd/cart/product-fetcher.go | 3 ++- cmd/checkout/main.go | 12 +++--------- cmd/order/main.go | 20 +++++++------------- cmd/profile/main.go | 13 +++---------- 7 files changed, 25 insertions(+), 56 deletions(-) diff --git a/Dockerfile b/Dockerfile index 83ef8b1..2411c7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,10 +47,11 @@ ENV CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} # because the renamed git.k6n.net/mats/* modules are not yet published. COPY --from=slaskfinder . ./slask-finder COPY --from=redisinventory . ./go-redis-inventory +COPY --from=platform . ./platform # This module's source (relay on .dockerignore to prune). COPY . ./go-cart-actor -RUN printf 'go 1.26.2\n\nuse (\n\t.\n\t../slask-finder\n\t../go-redis-inventory\n)\n' > ./go-cart-actor/go.work +RUN printf 'go 1.26.2\n\nuse (\n\t.\n\t../slask-finder\n\t../go-redis-inventory\n\t../platform\n)\n' > ./go-cart-actor/go.work WORKDIR /src/go-cart-actor # (Optional) If you do NOT check in generated protobuf code, uncomment generation: diff --git a/cmd/backoffice/main.go b/cmd/backoffice/main.go index 0953fed..ecf97bd 100644 --- a/cmd/backoffice/main.go +++ b/cmd/backoffice/main.go @@ -9,23 +9,17 @@ import ( "time" "git.k6n.net/mats/go-cart-actor/pkg/backofficeadmin" + "git.k6n.net/mats/platform/config" amqp "github.com/rabbitmq/amqp091-go" ) -func envOrDefault(key, def string) string { - if v := os.Getenv(key); v != "" { - return v - } - return def -} - func main() { - addr := envOrDefault("ADDR", ":8080") + addr := config.EnvString("ADDR", ":8080") amqpURL := os.Getenv("AMQP_URL") app, err := backofficeadmin.New(backofficeadmin.Config{ - DataDir: envOrDefault("CART_DIR", "data"), - CheckoutDataDir: envOrDefault("CHECKOUT_DIR", "checkout-data"), + DataDir: config.EnvString("CART_DIR", "data"), + CheckoutDataDir: config.EnvString("CHECKOUT_DIR", "checkout-data"), RedisAddress: os.Getenv("REDIS_ADDRESS"), RedisPassword: os.Getenv("REDIS_PASSWORD"), }) diff --git a/cmd/cart/main.go b/cmd/cart/main.go index 74fdd6e..f8afc9e 100644 --- a/cmd/cart/main.go +++ b/cmd/cart/main.go @@ -21,6 +21,7 @@ import ( "git.k6n.net/mats/go-cart-actor/pkg/telemetry" "git.k6n.net/mats/go-cart-actor/pkg/voucher" "git.k6n.net/mats/go-redis-inventory/pkg/inventory" + "git.k6n.net/mats/platform/config" "git.k6n.net/mats/slask-finder/pkg/messaging" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -52,7 +53,6 @@ var amqpUrl = os.Getenv("AMQP_URL") var redisAddress = os.Getenv("REDIS_ADDRESS") var redisPassword = os.Getenv("REDIS_PASSWORD") -// getEnv returns the value of the environment variable named by key, or def if unset/empty. // normalizeListenAddr accepts either a bare port ("8080") or a full listen // address (":8080", "0.0.0.0:8080") and returns a value usable by http.Server.Addr. func normalizeListenAddr(v string) string { @@ -62,14 +62,6 @@ func normalizeListenAddr(v string) string { return ":" + v } -// getEnv returns the value of the environment variable named by key, or def if unset/empty. -func getEnv(key, def string) string { - if v := os.Getenv(key); v != "" { - return v - } - return def -} - // loadUCPCartSigner loads the UCP ECDSA signing key from the path specified in // the UCP_SIGNING_KEY_PATH environment variable. Returns nil if unset or unreadable. func loadUCPCartSigner() *ucp.SigningConfig { @@ -129,7 +121,7 @@ func main() { // cartPort is the bare HTTP port. It drives both the local listener and the // port used to proxy to peer pods, so a cluster must run all pods on the // same CART_PORT. - cartPort := getEnv("CART_PORT", "8080") + cartPort := config.EnvString("CART_PORT", "8080") if i := strings.LastIndex(cartPort, ":"); i >= 0 { cartPort = cartPort[i+1:] } @@ -226,7 +218,7 @@ func main() { }), ) - diskStorage := actor.NewDiskStorage[cart.CartGrain](getEnv("CART_DIR", "data"), reg) + diskStorage := actor.NewDiskStorage[cart.CartGrain](config.EnvString("CART_DIR", "data"), reg) poolConfig := actor.GrainPoolConfig[cart.CartGrain]{ MutationRegistry: reg, Storage: diskStorage, @@ -415,7 +407,7 @@ func main() { mux.HandleFunc("/openapi.json", ServeEmbeddedOpenAPI) httpAddr := normalizeListenAddr(cartPort) - debugAddr := normalizeListenAddr(getEnv("CART_DEBUG_PORT", "8081")) + debugAddr := normalizeListenAddr(config.EnvString("CART_DEBUG_PORT", "8081")) srv := &http.Server{ Addr: httpAddr, diff --git a/cmd/cart/product-fetcher.go b/cmd/cart/product-fetcher.go index b1e271c..7b05fe1 100644 --- a/cmd/cart/product-fetcher.go +++ b/cmd/cart/product-fetcher.go @@ -10,6 +10,7 @@ import ( "strconv" messages "git.k6n.net/mats/go-cart-actor/proto/cart" + "git.k6n.net/mats/platform/config" ) // consumedKeys are product-document keys that are mapped to typed AddItem @@ -24,7 +25,7 @@ var consumedKeys = []string{ // PRODUCT_BASE_URL (the country argument is currently unused but kept for when // per-market routing returns). func getBaseUrl(country string) string { - return getEnv("PRODUCT_BASE_URL", "http://localhost:8082") + return config.EnvString("PRODUCT_BASE_URL", "http://localhost:8082") } // ProductItem is the flat product document served by GET /api/get/{sku}. diff --git a/cmd/checkout/main.go b/cmd/checkout/main.go index 1c68b8c..d393c77 100644 --- a/cmd/checkout/main.go +++ b/cmd/checkout/main.go @@ -17,6 +17,7 @@ import ( "git.k6n.net/mats/go-cart-actor/pkg/proxy" "git.k6n.net/mats/go-cart-actor/pkg/telemetry" "git.k6n.net/mats/go-redis-inventory/pkg/inventory" + "git.k6n.net/mats/platform/config" "github.com/adyen/adyen-go-api-library/v21/src/adyen" "github.com/adyen/adyen-go-api-library/v21/src/common" "github.com/prometheus/client_golang/prometheus" @@ -59,19 +60,12 @@ func selectTaxProvider() cart.TaxProvider { case "static": return cart.NewStaticTaxProvider() case "nordic": - return cart.NewNordicTaxProvider(envOrDefault("TAX_DEFAULT_COUNTRY", "SE")) + return cart.NewNordicTaxProvider(config.EnvString("TAX_DEFAULT_COUNTRY", "SE")) default: - return cart.NewNordicTaxProvider(envOrDefault("TAX_DEFAULT_COUNTRY", "SE")) + return cart.NewNordicTaxProvider(config.EnvString("TAX_DEFAULT_COUNTRY", "SE")) } } -func envOrDefault(key, def string) string { - if v := os.Getenv(key); v != "" { - return v - } - return def -} - // loadUCPCheckoutSigner loads the UCP ECDSA signing key from the path specified in // the UCP_SIGNING_KEY_PATH environment variable. Returns nil if unset or unreadable. func loadUCPCheckoutSigner() *ucp.SigningConfig { diff --git a/cmd/order/main.go b/cmd/order/main.go index bec48f8..2b9caeb 100644 --- a/cmd/order/main.go +++ b/cmd/order/main.go @@ -27,6 +27,7 @@ import ( ordermcp "git.k6n.net/mats/go-cart-actor/pkg/order/mcp" "git.k6n.net/mats/go-cart-actor/pkg/outbox" messages "git.k6n.net/mats/go-cart-actor/proto/order" + "git.k6n.net/mats/platform/config" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" @@ -49,9 +50,9 @@ type server struct { } func main() { - addr := envOr("ORDER_ADDR", ":8092") // :8090 cart, :8091 redirector - dataDir := envOr("ORDER_DATA", "data/orders") - flowsDir := envOr("ORDER_FLOWS", "data/order-flows") + addr := config.EnvString("ORDER_ADDR", ":8092") // :8090 cart, :8091 redirector + dataDir := config.EnvString("ORDER_DATA", "data/orders") + flowsDir := config.EnvString("ORDER_FLOWS", "data/order-flows") if err := os.MkdirAll(dataDir, 0o755); err != nil { log.Fatalf("create data dir: %v", err) } @@ -154,7 +155,7 @@ func main() { mux.HandleFunc("GET /api/orders/{id}", s.handleGet) mux.HandleFunc("GET /api/orders/{id}/events", s.handleEvents) - // Post-purchase lifecycle (the grain already supports these transitions). + // Post-purchase lifecycle (the grain already supports these transitions). mux.HandleFunc("POST /api/orders/{id}/fulfillments", s.handleFulfill) mux.HandleFunc("POST /api/orders/{id}/complete", s.handleComplete) mux.HandleFunc("POST /api/orders/{id}/cancel", s.handleCancel) @@ -462,9 +463,9 @@ func selectTaxProvider() order.TaxProvider { case "static": return order.NewStaticTaxProvider() case "nordic": - return order.NewNordicTaxProvider(envOr("TAX_DEFAULT_COUNTRY", "SE")) + return order.NewNordicTaxProvider(config.EnvString("TAX_DEFAULT_COUNTRY", "SE")) default: - return order.NewNordicTaxProvider(envOr("TAX_DEFAULT_COUNTRY", "SE")) + return order.NewNordicTaxProvider(config.EnvString("TAX_DEFAULT_COUNTRY", "SE")) } } @@ -505,13 +506,6 @@ func loadUCPOrderSigner() *ucp.SigningConfig { return cfg } -func envOr(key, def string) string { - if v := os.Getenv(key); v != "" { - return v - } - return def -} - func writeJSON(w http.ResponseWriter, status int, v any) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) diff --git a/cmd/profile/main.go b/cmd/profile/main.go index 475e583..69722a1 100644 --- a/cmd/profile/main.go +++ b/cmd/profile/main.go @@ -19,6 +19,7 @@ import ( "git.k6n.net/mats/go-cart-actor/pkg/profile" "git.k6n.net/mats/go-cart-actor/pkg/proxy" "git.k6n.net/mats/go-cart-actor/pkg/telemetry" + "git.k6n.net/mats/platform/config" "github.com/redis/go-redis/v9" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) @@ -88,18 +89,10 @@ func loadUCPProfileSigner() *ucp.SigningConfig { return cfg } -// getEnv returns the value of the environment variable named by key, or def if unset/empty. -func getEnv(key, def string) string { - if v := os.Getenv(key); v != "" { - return v - } - return def -} - func main() { reg := profile.NewProfileMutationRegistry() - profileDir := getEnv("PROFILE_DIR", "data/profiles") + profileDir := config.EnvString("PROFILE_DIR", "data/profiles") if err := os.MkdirAll(profileDir, 0755); err != nil { log.Printf("warning: could not create profile data directory %s: %v", profileDir, err) } @@ -214,7 +207,7 @@ func main() { }) srv := &http.Server{ - Addr: getEnv("PROFILE_ADDR", ":8080"), + Addr: config.EnvString("PROFILE_ADDR", ":8080"), BaseContext: func(net.Listener) context.Context { return ctx }, ReadTimeout: 10 * time.Second, WriteTimeout: 20 * time.Second,