chore: initial commit

This commit is contained in:
2024-04-16 22:27:52 +01:00
commit 531b5dabe2
194 changed files with 27071 additions and 0 deletions

99
cmd/auth-service/main.go Normal file
View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/hexolan/stocklet/internal/pkg/messaging"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/auth"
"github.com/hexolan/stocklet/internal/svc/auth/api"
"github.com/hexolan/stocklet/internal/svc/auth/controller"
)
func loadConfig() *auth.ServiceConfig {
// Load the main service configuration
cfg, err := auth.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "auth")
return cfg
}
func usePostgresController(cfg *auth.ServiceConfig) (auth.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client)
return controller, client
}
func useKafkaController(cfg *auth.ServiceConfig) (auth.ConsumerController, *kgo.Client) {
// load the Kafka configuration
if err := cfg.Kafka.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Kafka connection
client, err := messaging.NewKafkaConn(&cfg.Kafka, kgo.ConsumerGroup("auth-service"))
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewKafkaController(client)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := auth.NewAuthService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Create the consumer
consumer, consCl := useKafkaController(cfg)
defer consCl.Close()
consumer.Attach(svc)
// Serve the API interfaces
go consumer.Start()
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}

99
cmd/order-service/main.go Normal file
View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/hexolan/stocklet/internal/pkg/messaging"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/order"
"github.com/hexolan/stocklet/internal/svc/order/api"
"github.com/hexolan/stocklet/internal/svc/order/controller"
)
func loadConfig() *order.ServiceConfig {
// Load the core service configuration
cfg, err := order.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "order")
return cfg
}
func usePostgresController(cfg *order.ServiceConfig) (order.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client)
return controller, client
}
func useKafkaController(cfg *order.ServiceConfig) (order.ConsumerController, *kgo.Client) {
// load the Kafka configuration
if err := cfg.Kafka.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Kafka connection
client, err := messaging.NewKafkaConn(&cfg.Kafka, kgo.ConsumerGroup("order-service"))
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewKafkaController(client)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := order.NewOrderService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Create the consumer
consumer, consCl := useKafkaController(cfg)
defer consCl.Close()
consumer.Attach(svc)
// Serve/start the interfaces
go consumer.Start()
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}

View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/hexolan/stocklet/internal/pkg/messaging"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/payment"
"github.com/hexolan/stocklet/internal/svc/payment/api"
"github.com/hexolan/stocklet/internal/svc/payment/controller"
)
func loadConfig() *payment.ServiceConfig {
// Load the core service configuration
cfg, err := payment.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "payment")
return cfg
}
func usePostgresController(cfg *payment.ServiceConfig) (payment.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client)
return controller, client
}
func useKafkaController(cfg *payment.ServiceConfig) (payment.ConsumerController, *kgo.Client) {
// load the Kafka configuration
if err := cfg.Kafka.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Kafka connection
client, err := messaging.NewKafkaConn(&cfg.Kafka, kgo.ConsumerGroup("payment-service"))
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewKafkaController(client)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := payment.NewPaymentService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Create the consumer
consumer, consCl := useKafkaController(cfg)
defer consCl.Close()
consumer.Attach(svc)
// Serve/start the interfaces
go consumer.Start()
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}

View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/hexolan/stocklet/internal/pkg/messaging"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/product"
"github.com/hexolan/stocklet/internal/svc/product/api"
"github.com/hexolan/stocklet/internal/svc/product/controller"
)
func loadConfig() *product.ServiceConfig {
// Load the core service configuration
cfg, err := product.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "product")
return cfg
}
func usePostgresController(cfg *product.ServiceConfig) (product.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client)
return controller, client
}
func useKafkaController(cfg *product.ServiceConfig) (product.ConsumerController, *kgo.Client) {
// load the Kafka configuration
if err := cfg.Kafka.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Kafka connection
client, err := messaging.NewKafkaConn(&cfg.Kafka, kgo.ConsumerGroup("product-service"))
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewKafkaController(client)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := product.NewProductService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Create the consumer
consumer, consCl := useKafkaController(cfg)
defer consCl.Close()
consumer.Attach(svc)
// Serve/start the interfaces
go consumer.Start()
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}

View File

@@ -0,0 +1,63 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/hexolan/stocklet/internal/pkg/config"
)
// Init Container Configuration
type InitConfig struct {
// Name of the service (e.g. 'auth' or 'order')
//
// Env Var: "INIT_SVC_NAME"
ServiceName string
// Env Var: "INIT_MIGRATIONS" (optional. accepts 'false')
// Defaults to true
ApplyMigrations bool
// 'ApplyDebezium' will default to false unless
// the debezium host is provided.
//
// Env Var: "INIT_DEBEZIUM_HOST" (optional)
// e.g. "http://debezium:8083"
ApplyDebezium bool
DebeziumHost string
}
func (opts *InitConfig) Load() error {
// ServiceName
opt, err := config.RequireFromEnv("INIT_SVC_NAME")
if err != nil {
return err
}
opts.ServiceName = opt
// ApplyMigrations
opts.ApplyMigrations = true
if opt, _ := config.RequireFromEnv("INIT_MIGRATIONS"); opt == "false" {
opts.ApplyMigrations = false
}
// ApplyDebezium and DebeziumHost
if opt, err := config.RequireFromEnv("INIT_DEBEZIUM_HOST"); err == nil {
opts.ApplyDebezium = true
opts.DebeziumHost = opt
}
return nil
}

View File

@@ -0,0 +1,67 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"bytes"
"encoding/json"
"net/http"
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/config"
)
func applyPostgresOutbox(cfg *InitConfig, conf *config.PostgresConfig) {
payloadB, err := json.Marshal(map[string]string{
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"plugin.name": "pgoutput",
"tasks.max": "1",
"table.include.list": "public.event_outbox",
"transforms": "outbox",
"transforms.outbox.type": "io.debezium.transforms.outbox.EventRouter",
"transforms.outbox.route.topic.replacement": "${routedByValue}",
"value.converter": "io.debezium.converters.BinaryDataConverter",
"topic.prefix": cfg.ServiceName,
"database.hostname": conf.Host,
"database.port": conf.Port,
"database.user": conf.Username,
"database.password": conf.Password,
"database.dbname": conf.Database,
})
if err != nil {
log.Panic().Err(err).Msg("debezium connect: failed to marshal debezium cfg")
}
url := cfg.DebeziumHost + "/connectors/" + cfg.ServiceName + "-outbox/config"
log.Info().Str("url", url).Msg("debezium url")
req, err := http.NewRequest(
"PUT",
url,
bytes.NewReader(payloadB),
)
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
log.Panic().Err(err).Msg("debezium connect: failed to perform debezium request")
}
log.Info().Str("status", res.Status).Msg("debezium connect: applied outbox config")
}

52
cmd/service-init/main.go Normal file
View File

@@ -0,0 +1,52 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/config"
)
func main() {
// Load the init container cfg options
cfg := InitConfig{}
if err := cfg.Load(); err != nil {
log.Panic().Err(err).Msg("missing required configuration")
}
// If migrations or debezium are enabled,
// then a database configuration will be required.
if cfg.ApplyMigrations || cfg.ApplyDebezium {
// Support for dynamic loading of configuration
// (e.g. mongo config instead of postgres config)
pgConf := config.PostgresConfig{}
if err := pgConf.Load(); err == nil {
// Using postgres as a database.
if cfg.ApplyMigrations {
applyPostgresMigrations(&pgConf)
}
if cfg.ApplyDebezium {
applyPostgresOutbox(&cfg, &pgConf)
}
} else {
log.Panic().Msg("unable to load any db configs (unable to perform migrations or apply connector cfgs)")
}
}
log.Info().Str("svc", cfg.ServiceName).Msg("completed init for service")
}

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/config"
)
func applyPostgresMigrations(conf *config.PostgresConfig) {
m, err := migrate.New("file:///migrations", conf.GetDSN())
if err != nil {
log.Panic().Err(err).Msg("migrate: failed to open client")
}
err = m.Up()
if err != nil {
if err.Error() == "no change" {
log.Info().Err(err).Msg("migrate: migrations up to date")
} else {
log.Panic().Err(err).Msg("migrate: raised when performing db migration")
}
}
log.Info().Msg("migrate: succesfully performed postgres migrations")
}

View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/hexolan/stocklet/internal/pkg/messaging"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/shipping"
"github.com/hexolan/stocklet/internal/svc/shipping/api"
"github.com/hexolan/stocklet/internal/svc/shipping/controller"
)
func loadConfig() *shipping.ServiceConfig {
// Load the core service configuration
cfg, err := shipping.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "shipping")
return cfg
}
func usePostgresController(cfg *shipping.ServiceConfig) (shipping.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client)
return controller, client
}
func useKafkaController(cfg *shipping.ServiceConfig) (shipping.ConsumerController, *kgo.Client) {
// load the Kafka configuration
if err := cfg.Kafka.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Kafka connection
client, err := messaging.NewKafkaConn(&cfg.Kafka, kgo.ConsumerGroup("shipping-service"))
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewKafkaController(client)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := shipping.NewShippingService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Create the consumer
consumer, consCl := useKafkaController(cfg)
defer consCl.Close()
consumer.Attach(svc)
// Serve/start the interfaces
go consumer.Start()
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}

75
cmd/user-service/main.go Normal file
View File

@@ -0,0 +1,75 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/user"
"github.com/hexolan/stocklet/internal/svc/user/api"
"github.com/hexolan/stocklet/internal/svc/user/controller"
)
func loadConfig() *user.ServiceConfig {
// Load the core service configuration
cfg, err := user.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "user")
return cfg
}
func usePostgresController(cfg *user.ServiceConfig) (user.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client, &cfg.ServiceOpts)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := user.NewUserService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Serve/start the interfaces
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}

View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/zerolog/log"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/hexolan/stocklet/internal/pkg/messaging"
"github.com/hexolan/stocklet/internal/pkg/metrics"
"github.com/hexolan/stocklet/internal/pkg/serve"
"github.com/hexolan/stocklet/internal/pkg/storage"
"github.com/hexolan/stocklet/internal/svc/warehouse"
"github.com/hexolan/stocklet/internal/svc/warehouse/api"
"github.com/hexolan/stocklet/internal/svc/warehouse/controller"
)
func loadConfig() *warehouse.ServiceConfig {
// Load the core service configuration
cfg, err := warehouse.NewServiceConfig()
if err != nil {
log.Panic().Err(err).Msg("")
}
// Configure metrics (logging and OTEL)
metrics.ConfigureLogger()
metrics.InitTracerProvider(&cfg.Shared.Otel, "warehouse")
return cfg
}
func usePostgresController(cfg *warehouse.ServiceConfig) (warehouse.StorageController, *pgxpool.Pool) {
// load the Postgres configuration
if err := cfg.Postgres.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Postgres connection
client, err := storage.NewPostgresConn(&cfg.Postgres)
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewPostgresController(client)
return controller, client
}
func useKafkaController(cfg *warehouse.ServiceConfig) (warehouse.ConsumerController, *kgo.Client) {
// load the Kafka configuration
if err := cfg.Kafka.Load(); err != nil {
log.Panic().Err(err).Msg("")
}
// open a Kafka connection
client, err := messaging.NewKafkaConn(&cfg.Kafka, kgo.ConsumerGroup("warehouse-service"))
if err != nil {
log.Panic().Err(err).Msg("")
}
controller := controller.NewKafkaController(client)
return controller, client
}
func main() {
cfg := loadConfig()
// Create the storage controller
store, storeCl := usePostgresController(cfg)
defer storeCl.Close()
// Create the service (& API interfaces)
svc := warehouse.NewWarehouseService(cfg, store)
grpcSvr := api.PrepareGrpc(cfg, svc)
gatewayMux := api.PrepareGateway(cfg)
// Create the consumer
consumer, consCl := useKafkaController(cfg)
defer consCl.Close()
consumer.Attach(svc)
// Serve/start the interfaces
go consumer.Start()
go serve.Gateway(gatewayMux)
serve.Grpc(grpcSvr)
}