-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
562845a
commit b989c82
Showing
12 changed files
with
395 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,4 +20,5 @@ go.work | |
# Other | ||
.idea | ||
.DS_Store | ||
.env | ||
.env | ||
/db-data/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# build a tiny docker image | ||
FROM alpine:latest | ||
|
||
RUN mkdir /app | ||
|
||
COPY apiApp /app | ||
|
||
CMD ["/app/apiApp"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
API_APP_BINARY=apiApp | ||
|
||
## up: starts all containers in the background without forcing build. | ||
up: | ||
@echo "Starting Docker images..." | ||
docker-compose up -d | ||
@echo "Docker images started!" | ||
|
||
## up_build: stops docker-compose (if running), builds all projects and starts docker compose. | ||
up_build: build_app | ||
@echo "Stopping docker images (if running...)" | ||
docker-compose down | ||
@echo "Building (when required) and starting docker images..." | ||
docker-compose up --build -d | ||
@echo "Docker images built and started!" | ||
|
||
## down: stop docker compose. | ||
down: | ||
@echo "Stopping docker compose..." | ||
docker-compose down | ||
@echo "Done!" | ||
|
||
## build_app: builds the app binary as a linux executable. | ||
build_app: | ||
@echo "Building app binary..." | ||
cd . && env GOOS=linux CGO_ENABLED=0 go build -o ${API_APP_BINARY} ./cmd/api | ||
@echo "Done!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,123 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"github.com/joho/godotenv" | ||
"github.com/vladyslavpavlenko/genesis-api-project/internal/config" | ||
"github.com/vladyslavpavlenko/genesis-api-project/internal/handlers" | ||
"github.com/vladyslavpavlenko/genesis-api-project/internal/models" | ||
"gorm.io/driver/postgres" | ||
"gorm.io/gorm" | ||
"log" | ||
"os" | ||
"time" | ||
) | ||
|
||
var counts int64 | ||
|
||
func setup(app *config.AppConfig) error { | ||
// Get environment variables | ||
env, err := loadEvnVariables() | ||
// Connect to the database and run migrations | ||
db, err := connectToDB() | ||
if err != nil { | ||
return err | ||
log.Fatal(err) | ||
} | ||
|
||
app.Env = env | ||
|
||
// Connect to the database and run migrations | ||
db, err := connectToPostgresAndMigrate(env) | ||
err = runDBMigrations(db) | ||
if err != nil { | ||
return err | ||
log.Fatal(err) | ||
} | ||
|
||
app.DB = db | ||
|
||
app.Models = models.New(db) | ||
repo := handlers.NewRepo(app) | ||
handlers.NewHandlers(repo) | ||
render.NewRenderer(app) | ||
|
||
return nil | ||
} | ||
|
||
// loadEvnVariables loads variables from the .env file. | ||
func loadEvnVariables() (*config.EnvVariables, error) { | ||
err := godotenv.Load() | ||
func openDB(dsn string) (*gorm.DB, error) { | ||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting environment variables: %v", err) | ||
return nil, err | ||
} | ||
|
||
postgresHost := os.Getenv("POSTGRES_HOST") | ||
postgresUser := os.Getenv("POSTGRES_USER") | ||
postgresPass := os.Getenv("POSTGRES_PASS") | ||
postgresDBName := os.Getenv("POSTGRES_DBNAME") | ||
jwtSecret := os.Getenv("JWT_SECRET") | ||
|
||
return &config.EnvVariables{ | ||
PostgresHost: postgresHost, | ||
PostgresUser: postgresUser, | ||
PostgresPass: postgresPass, | ||
PostgresDBName: postgresDBName, | ||
}, nil | ||
return db, nil | ||
} | ||
|
||
// connectToPostgresAndMigrate initializes a PostgreSQL db session and runs GORM migrations. | ||
func connectToPostgresAndMigrate(env *config.EnvVariables) (*gorm.DB, error) { | ||
dsn := fmt.Sprintf("host=%s user=%s dbname=%s password=%s sslmode=disable", | ||
env.PostgresHost, env.PostgresUser, env.PostgresDBName, env.PostgresPass) | ||
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) | ||
func connectToDB() (*gorm.DB, error) { | ||
dsn := os.Getenv("DSN") | ||
|
||
for { | ||
connection, err := openDB(dsn) | ||
if err != nil { | ||
log.Println("Postgres not yet ready...") | ||
counts++ | ||
} else { | ||
log.Println("Connected to Postgres!") | ||
return connection, nil | ||
} | ||
|
||
if counts > 10 { | ||
log.Println(err) | ||
return nil, err | ||
} | ||
|
||
log.Println("Backing off for two seconds...") | ||
time.Sleep(2 * time.Second) | ||
continue | ||
} | ||
} | ||
|
||
// runDBMigrations runs database migrations. | ||
func runDBMigrations(db *gorm.DB) error { | ||
log.Println("Running migrations...") | ||
// create tables | ||
err := db.AutoMigrate(&models.User{}) | ||
if err != nil { | ||
log.Fatal("could not connect: ", err) | ||
return err | ||
} | ||
|
||
return db, nil | ||
err = db.AutoMigrate(&models.Currency{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = db.AutoMigrate(&models.Subscription{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// populate tables with initial data | ||
err = createInitialCurrencies(db) | ||
if err != nil { | ||
return errors.New(fmt.Sprint("error creating initial currencies:", err)) | ||
} | ||
|
||
log.Println("Database migrated!") | ||
|
||
return nil | ||
} | ||
|
||
// createInitialCurrencies creates initial currencies in the `currencies` table. | ||
func createInitialCurrencies(db *gorm.DB) error { | ||
var count int64 | ||
|
||
if err := db.Model(&models.Currency{}).Count(&count).Error; err != nil { | ||
return err | ||
} | ||
|
||
if count > 0 { | ||
return nil | ||
} | ||
|
||
initialCurrencies := []models.Currency{ | ||
{Code: "USD", Name: "United States Dollar"}, | ||
{Code: "UAH", Name: "Ukrainian Hryvnia"}, | ||
} | ||
|
||
if err := db.Create(&initialCurrencies).Error; err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
services: | ||
postgres: | ||
image: 'postgres:14.0' | ||
ports: | ||
- "5432:5432" | ||
restart: always | ||
deploy: | ||
mode: replicated | ||
replicas: 1 | ||
environment: | ||
POSTGRES_USER: postgres | ||
POSTGRES_PASSWORD: password | ||
POSTGRES_DB: emails | ||
volumes: | ||
- ./db-data/postgres/:/var/lib/postgresql/data/ | ||
|
||
api-app: | ||
build: | ||
context: . | ||
dockerfile: Dockerfile | ||
ports: | ||
- "8080:8080" | ||
restart: always | ||
deploy: | ||
mode: replicated | ||
replicas: 1 | ||
environment: | ||
DSN: "host=postgres port=5432 user=postgres password=password dbname=emails sslmode=disable timezone=UTC connect_timeout=5" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,12 @@ | ||
package config | ||
|
||
import ( | ||
"github.com/vladyslavpavlenko/genesis-api-project/internal/models" | ||
"gorm.io/gorm" | ||
) | ||
|
||
// AppConfig holds the application config. | ||
type AppConfig struct { | ||
DB *gorm.DB | ||
Env *EnvVariables | ||
} | ||
|
||
// EnvVariables holds environment variables used in the application. | ||
type EnvVariables struct { | ||
PostgresHost string | ||
PostgresUser string | ||
PostgresPass string | ||
PostgresDBName string | ||
DB *gorm.DB | ||
Models models.Models | ||
} |
Oops, something went wrong.