Initial commit
This commit is contained in:
commit
01cd6d8e01
8
.idea/database.iml
generated
Normal file
8
.idea/database.iml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/database.iml" filepath="$PROJECT_DIR$/.idea/database.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
9
.idea/workspace.xml
generated
Normal file
9
.idea/workspace.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectViewState">
|
||||
<option name="autoscrollFromSource" value="true" />
|
||||
<option name="autoscrollToSource" value="true" />
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
</project>
|
21
config.go
Normal file
21
config.go
Normal file
@ -0,0 +1,21 @@
|
||||
package database
|
||||
|
||||
type Config struct {
|
||||
DSN string `yaml:"dsn" envconfig:"DSN"`
|
||||
MaxIdleConns int `yaml:"maxIdleConns" envconfig:"MAX_IDLE_CONNS"`
|
||||
MaxOpenConns int `yaml:"maxOpenConns" envconfig:"MAX_OPEN_CONNS"`
|
||||
ConnMaxLifetime int `yaml:"connMaxLifetime" envconfig:"CONNS_MAX_LIFE_TIME"`
|
||||
AutoMigrate bool `yaml:"autoMigrate" envconfig:"AUTO_MIGRATE"`
|
||||
ShowSql bool `yaml:"showSql" envconfig:"SHOW_SQL"`
|
||||
}
|
||||
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
DSN: "host=localhost user=gate password=gate dbname=gate port=5432 sslmode=disable",
|
||||
MaxIdleConns: 10,
|
||||
MaxOpenConns: 20,
|
||||
ConnMaxLifetime: 3600,
|
||||
AutoMigrate: false,
|
||||
ShowSql: false,
|
||||
}
|
||||
}
|
27
entities.go
Normal file
27
entities.go
Normal file
@ -0,0 +1,27 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/satori/go.uuid"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// EntityBase contains common columns for all tables.
|
||||
type EntityBase struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt *time.Time
|
||||
//DeletedAt *time.Time
|
||||
}
|
||||
|
||||
// BeforeCreate will set a UUID rather than numeric ID.
|
||||
func (base *EntityBase) BeforeCreate(tx *gorm.DB) error {
|
||||
base.ID = uuid.NewV4()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (base *EntityBase) BeforeUpdate(tx *gorm.DB) error {
|
||||
now := time.Now()
|
||||
base.UpdatedAt = &now
|
||||
return nil
|
||||
}
|
29
go.mod
Normal file
29
go.mod
Normal file
@ -0,0 +1,29 @@
|
||||
module netgarden.dev/maf/database
|
||||
|
||||
go 1.24.1
|
||||
|
||||
replace netgarden.dev/maf/maf => ../maf
|
||||
|
||||
require (
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
gorm.io/driver/postgres v1.5.11
|
||||
gorm.io/gorm v1.25.12
|
||||
netgarden.dev/maf/maf v0.0.0-20250327102624-f25d54ddf786
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/elliotchance/orderedmap v1.6.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
51
go.sum
Normal file
51
go.sum
Normal file
@ -0,0 +1,51 @@
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/elliotchance/orderedmap v1.6.0 h1:xjn+kbbKXeDq6v9RVE+WYwRbYfAZKvlWfcJNxM8pvEw=
|
||||
github.com/elliotchance/orderedmap v1.6.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
|
||||
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
16
interfaces.go
Normal file
16
interfaces.go
Normal file
@ -0,0 +1,16 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"netgarden.dev/maf/maf"
|
||||
)
|
||||
|
||||
type Consumer interface {
|
||||
maf.Module
|
||||
SetDB(db *gorm.DB)
|
||||
}
|
||||
|
||||
type EntitiesProvider interface {
|
||||
maf.Module
|
||||
GetDBEntities() []interface{}
|
||||
}
|
162
module.go
Normal file
162
module.go
Normal file
@ -0,0 +1,162 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
"log/slog"
|
||||
"netgarden.dev/maf/maf"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewModule() *Module {
|
||||
return &Module{}
|
||||
}
|
||||
|
||||
type Module struct {
|
||||
manager *maf.Manager
|
||||
config *Config
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (m *Module) GetID() string {
|
||||
return "database"
|
||||
}
|
||||
|
||||
func (m *Module) GetName() string {
|
||||
return "database"
|
||||
}
|
||||
|
||||
func (m *Module) SetManager(manager *maf.Manager) {
|
||||
m.manager = manager
|
||||
}
|
||||
|
||||
func (m *Module) CreateConfig() interface{} {
|
||||
return NewConfig()
|
||||
}
|
||||
|
||||
func (m *Module) SetConfig(cfg interface{}) {
|
||||
m.config = cfg.(*Config)
|
||||
}
|
||||
|
||||
func (m *Module) PreInitialize() error {
|
||||
|
||||
var err error
|
||||
|
||||
m.db, err = m.connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.autoMigrate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.notifyConsumers()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Module) connect() (*gorm.DB, error) {
|
||||
|
||||
gormPgConfig := postgres.Config{
|
||||
DSN: m.config.DSN,
|
||||
}
|
||||
|
||||
gormConfig := &gorm.Config{}
|
||||
if m.config.ShowSql {
|
||||
gormConfig.Logger = logger.Default.LogMode(logger.Info)
|
||||
}
|
||||
|
||||
var db *gorm.DB
|
||||
var err error
|
||||
|
||||
db, err = gorm.Open(postgres.New(gormPgConfig), gormConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sqlDB.SetMaxIdleConns(m.config.MaxIdleConns)
|
||||
sqlDB.SetMaxOpenConns(m.config.MaxOpenConns)
|
||||
sqlDB.SetConnMaxLifetime(time.Second * time.Duration(m.config.ConnMaxLifetime))
|
||||
|
||||
err = sqlDB.Ping()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, err
|
||||
}
|
||||
|
||||
func (m *Module) autoMigrate() error {
|
||||
|
||||
if !m.config.AutoMigrate {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
err = m.autoMigrateTables()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Module) autoMigrateTables() error {
|
||||
|
||||
slog.Info("Storage tables auto migration starting ...")
|
||||
|
||||
entities := make([]interface{}, 0)
|
||||
for _, module := range m.manager.GetModulesList() {
|
||||
if consumer, ok := module.(EntitiesProvider); ok {
|
||||
consumerEntities := consumer.GetDBEntities()
|
||||
if consumerEntities != nil && len(consumerEntities) > 0 {
|
||||
entities = append(entities, consumerEntities...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
err = m.db.AutoMigrate(entities...)
|
||||
|
||||
slog.Info("Storage tables auto migration finished ...")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Module) notifyConsumers() {
|
||||
for _, module := range m.manager.GetModulesList() {
|
||||
if consumer, ok := module.(Consumer); ok {
|
||||
consumer.SetDB(m.db)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Module) Stop() error {
|
||||
|
||||
if m.db == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sqlDB, err := m.db.DB()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = sqlDB.Close()
|
||||
m.db = nil
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Module) GetDB() *gorm.DB {
|
||||
return m.db
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user