add two new packages - envutils and db, add .gitignore
This commit is contained in:
parent
26abcb7a45
commit
d39a6317fc
|
@ -0,0 +1 @@
|
|||
.env.local
|
|
@ -0,0 +1,82 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
envutils "github.com/zdam-egzamin-zawodowy/backend/pkg/utils/env"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zdam-egzamin-zawodowy/backend/internal/models"
|
||||
)
|
||||
|
||||
const (
|
||||
extensions = `
|
||||
CREATE EXTENSION IF NOT EXISTS tsm_system_rows;
|
||||
`
|
||||
)
|
||||
|
||||
func init() {
|
||||
orm.RegisterTable((*models.QualificationToProfession)(nil))
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
DebugHook bool
|
||||
}
|
||||
|
||||
func New(cfg *Config) (*pg.DB, error) {
|
||||
db := pg.Connect(prepareOptions())
|
||||
if err := createSchema(db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg != nil {
|
||||
if cfg.DebugHook {
|
||||
db.AddQueryHook(DebugHook{
|
||||
Entry: logrus.WithField("package", "internal/db"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func prepareOptions() *pg.Options {
|
||||
return &pg.Options{
|
||||
User: os.Getenv("DB_USER"),
|
||||
Password: os.Getenv("DB_PASSWORD"),
|
||||
Database: os.Getenv("DB_NAME"),
|
||||
Addr: os.Getenv("DB_HOST") + ":" + os.Getenv("DB_PORT"),
|
||||
PoolSize: envutils.GetenvInt("DB_POOL_SIZE"),
|
||||
}
|
||||
}
|
||||
|
||||
func createSchema(db *pg.DB) error {
|
||||
return db.RunInTransaction(context.Background(), func(tx *pg.Tx) error {
|
||||
if _, err := tx.Exec(extensions); err != nil {
|
||||
return errors.Wrap(err, "createSchema")
|
||||
}
|
||||
|
||||
models := []interface{}{
|
||||
(*models.User)(nil),
|
||||
(*models.Profession)(nil),
|
||||
(*models.Qualification)(nil),
|
||||
(*models.QualificationToProfession)(nil),
|
||||
(*models.Question)(nil),
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
err := tx.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: true,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "createSchema")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type DebugHook struct {
|
||||
Entry *logrus.Entry
|
||||
}
|
||||
|
||||
var _ pg.QueryHook = (*DebugHook)(nil)
|
||||
|
||||
func (logger DebugHook) BeforeQuery(ctx context.Context, evt *pg.QueryEvent) (context.Context, error) {
|
||||
q, err := evt.FormattedQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if evt.Err != nil {
|
||||
logger.Entry.Errorf("%s executing a query:\n%s\n", evt.Err, q)
|
||||
} else {
|
||||
logger.Entry.Info(string(q))
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (DebugHook) AfterQuery(context.Context, *pg.QueryEvent) error {
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#!/bin/sh
|
||||
cd ./internal/graphql
|
||||
go run github.com/99designs/gqlgen
|
||||
go mod tidy
|
||||
go mod tidy
|
||||
cd ../..
|
|
@ -11,19 +11,21 @@ import (
|
|||
)
|
||||
|
||||
type Question struct {
|
||||
tableName struct{} `pg:"alias:question"`
|
||||
|
||||
ID int `json:"id" xml:"id" gqlgen:"id"`
|
||||
From string `pg:",unique:group_1" json:"from" xml:"from" gqlgen:"from"`
|
||||
Content string `pg:",unique:group_1,notnull" json:"content" xml:"content" gqlgen:"content"`
|
||||
Explanation string `json:"explanation" xml:"explanation" gqlgen:"explanation"`
|
||||
CorrectAnswer Answer `pg:",unique:group_1,notnull" json:"correctAnswer" xml:"correctAnswer" gqlgen:"correctAnswer"`
|
||||
Image string `json:"image" xml:"image" gqlgen:"image"`
|
||||
AnswerA Answer `json:"answerA" xml:"answerA" gqlgen:"answerA"`
|
||||
AnswerA Answer `pg:"answer_a" json:"answerA" xml:"answerA" gqlgen:"answerA"`
|
||||
AnswerAImage string `pg:"answer_a_image" json:"answerAImage" xml:"answerAImage" gqlgen:"answerAImage"`
|
||||
AnswerB Answer `json:"answerB" xml:"answerB" gqlgen:"answerB"`
|
||||
AnswerB Answer `pg:"answer_b" json:"answerB" xml:"answerB" gqlgen:"answerB"`
|
||||
AnswerBImage string `pg:"answer_b_image" json:"answerBImage" xml:"answerBImage" gqlgen:"answerBImage"`
|
||||
AnswerC Answer `json:"answerC" xml:"answerC" gqlgen:"answerC"`
|
||||
AnswerC Answer `pg:"answer_c" json:"answerC" xml:"answerC" gqlgen:"answerC"`
|
||||
AnswerCImage string `pg:"answer_c_image" json:"answerCImage" xml:"answerCImage" gqlgen:"answerCImage"`
|
||||
AnswerD Answer `json:"answerD" xml:"answerD" gqlgen:"answerD"`
|
||||
AnswerD Answer `pg:"answer_d" json:"answerD" xml:"answerD" gqlgen:"answerD"`
|
||||
AnswerDImage string `pg:"answer_d_image" json:"answerDImage" xml:"answerDImage" gqlgen:"answerDImage"`
|
||||
QualificationID int `pg:",unique:group_1,on_delete:CASCADE" json:"qualificationID" xml:"qualificationID" gqlgen:"qualificationID"`
|
||||
Qualification *Qualification `pg:"rel:has-one" json:"qualification" xml:"qualification" gqlgen:"qualification"`
|
||||
|
|
14
main.go
14
main.go
|
@ -7,11 +7,15 @@ import (
|
|||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zdam-egzamin-zawodowy/backend/internal/db"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zdam-egzamin-zawodowy/backend/pkg/mode"
|
||||
envutils "github.com/zdam-egzamin-zawodowy/backend/pkg/utils/env"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -25,6 +29,14 @@ func init() {
|
|||
}
|
||||
|
||||
func main() {
|
||||
_, err := db.New(&db.Config{
|
||||
DebugHook: envutils.GetenvBool("LOG_DB_QUERIES"),
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Fatal(errors.Wrap(err, "Error establishing a database connection"))
|
||||
}
|
||||
logrus.Info("Database connection established")
|
||||
|
||||
router := gin.Default()
|
||||
if mode.Get() == mode.DevelopmentMode {
|
||||
router.Use(cors.New(cors.Config{
|
||||
|
@ -35,7 +47,7 @@ func main() {
|
|||
ExposeHeaders: []string{"X-Access-Token", "X-Refresh-Token"},
|
||||
AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"},
|
||||
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization"},
|
||||
AllowWebSockets: true,
|
||||
AllowWebSockets: false,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package envutils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GetenvInt(key string) int {
|
||||
str := os.Getenv(key)
|
||||
if str == "" {
|
||||
return 0
|
||||
}
|
||||
i, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func GetenvBool(key string) bool {
|
||||
str := os.Getenv(key)
|
||||
if str == "" {
|
||||
return false
|
||||
}
|
||||
return str == "true" || str == "1"
|
||||
}
|
Reference in New Issue