package database import ( "context" "os" "database/sql" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "go.uber.org/fx" "gorm.io/driver/sqlite" "gorm.io/gorm" "sneak.berlin/go/directory/internal/config" "sneak.berlin/go/directory/internal/globals" "sneak.berlin/go/directory/internal/logger" "sneak.berlin/go/util" // spooky action at a distance! // this populates the environment // from a ./.env file automatically // for development configuration. // .env contents should be things like // `DBURL=postgres://user:pass@.../` // (without the backticks, of course) _ "github.com/joho/godotenv/autoload" ) type DatabaseParams struct { fx.In Logger *logger.Logger Config *config.Config Globals *globals.Globals } type Database struct { URL string log *zerolog.Logger params *DatabaseParams DB *gorm.DB SQLDB *sql.DB dbdir string dbfn string } func New(lc fx.Lifecycle, params DatabaseParams) (*Database, error) { s := new(Database) s.params = ¶ms s.log = params.Logger.Get() s.log.Info().Msg("Database instantiated") lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { s.log.Info().Msg("Database OnStart Hook") // FIXME connect to db return nil }, OnStop: func(ctx context.Context) error { // FIXME disconnect from db return nil }, }) return s, nil } func (d *Database) Close() { d.log.Info().Msg("Database Close()") } func (d *Database) Get() (*gorm.DB, error) { if d.DB == nil { err := d.Connect() if err != nil { d.log.Error().Err(err).Msg("failed to connect to database") return nil, err } } return d.DB, nil } func (d *Database) Connect() error { // FIXME make this get the data dir path from config d.dbdir = os.Getenv("HOME") err := util.Mkdirp(d.dbdir) if err != nil { d.log.Error(). Err(err). Str("dbdir", d.dbdir). Msg("unable to create directory") return err } d.dbfn = d.dbdir + "/" + d.params.Globals.Appname + ".db" d.log.Info(). Str("file", d.dbfn). Msg("opening store db") // Open the database using the pure Go SQLite driver sqlDB, err := sql.Open("sqlite", d.dbfn+"?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)") if err != nil { d.log.Error().Err(err).Msg("failed to open database") return err } d.SQLDB = sqlDB // Use the generic Gorm SQL driver to integrate it db, err := gorm.Open(sqlite.Dialector{Conn: d.SQLDB}, &gorm.Config{}) if err != nil { log.Error().Err(err).Msg("failed to connect database") return err } d.DB = db return nil }