mirror of
https://github.com/hexolan/stocklet.git
synced 2026-03-26 11:41:18 +00:00
chore: initial commit
This commit is contained in:
99
cmd/auth-service/main.go
Normal file
99
cmd/auth-service/main.go
Normal 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
99
cmd/order-service/main.go
Normal 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)
|
||||
}
|
||||
99
cmd/payment-service/main.go
Normal file
99
cmd/payment-service/main.go
Normal 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)
|
||||
}
|
||||
99
cmd/product-service/main.go
Normal file
99
cmd/product-service/main.go
Normal 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)
|
||||
}
|
||||
63
cmd/service-init/config.go
Normal file
63
cmd/service-init/config.go
Normal 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
|
||||
}
|
||||
67
cmd/service-init/connectors.go
Normal file
67
cmd/service-init/connectors.go
Normal 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
52
cmd/service-init/main.go
Normal 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")
|
||||
}
|
||||
43
cmd/service-init/migrations.go
Normal file
43
cmd/service-init/migrations.go
Normal 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")
|
||||
}
|
||||
99
cmd/shipping-service/main.go
Normal file
99
cmd/shipping-service/main.go
Normal 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
75
cmd/user-service/main.go
Normal 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)
|
||||
}
|
||||
99
cmd/warehouse-service/main.go
Normal file
99
cmd/warehouse-service/main.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user