ticket-pimp/cmd/main.go

148 lines
2.9 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"ticket-pimp/internal/controller"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/external"
"ticket-pimp/client/discord"
"ticket-pimp/client/telegram"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/jackc/pgx/v5/stdlib"
"github.com/pkg/errors"
migrate "github.com/rubenv/sql-migrate"
"golang.org/x/sync/errgroup"
)
const migrationfile = "../internal/storage/migrate"
func main() {
log.Print("started")
env := flag.Int("env", -1, "0 for development env file, 1 for production environment run, missing flag for build")
flag.Parse()
var envPath string
switch *env {
case 0:
envPath = ".env"
case 1:
envPath = "../docker/prod.env"
default:
envPath = "prod.env"
}
config := domain.InitConfig(envPath)
run(&config)
}
func Go(ctx context.Context, fns ...func(context.Context) error) error {
group, ctx := errgroup.WithContext(ctx)
for _, fn := range fns {
fn := fn
group.Go(func() error {
return fn(ctx)
})
}
return group.Wait()
}
func applyMigrations(connString string) {
// Apply migrations:
dbConnConfig, err := pgxpool.ParseConfig(connString)
if err != nil {
log.Fatalf("unable to parse connString: %v", err)
}
migrations := &migrate.FileMigrationSource{
Dir: migrationfile,
}
db := stdlib.OpenDB(*dbConnConfig.ConnConfig)
const dialect = "postgres"
n, err := migrate.Exec(db, dialect, migrations, migrate.Up)
if err != nil {
log.Fatalf("unable to handle migrations: %v", err)
}
fmt.Printf("Applied %d migrations!\n", n)
err = db.Close()
if err != nil {
log.Fatal("unable to close db connection")
}
}
func run(c *domain.Config) {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGTERM)
defer cancel()
// -- DB connection init -- START
connString := fmt.Sprintf(
"postgresql://%s:%s@%s:%s/%s",
c.DB.User, c.DB.Pass, c.DB.Host, c.DB.Port, c.DB.Name,
)
conn, err := pgxpool.New(
ctx,
connString)
if err != nil {
log.Fatalf("DB connection failed: %v", err)
}
// Apply migrations:
applyMigrations(connString)
// Init services instances:
git := external.NewGit(c.Git)
cloud := external.NewCloud(c.Cloud)
coda := external.NewCoda(c.Coda)
// Controller instance init:
controller := controller.NewApp(
git,
cloud,
coda,
conn,
c,
)
Go(ctx,
func(ctx context.Context) error {
opts := discord.DiscordOptions{
Controller: controller,
Config: c,
}
if err := discord.Run(c, opts); err != nil {
return errors.Errorf("discord bot cannot be runned: %v", err)
}
return nil
},
func(ctx context.Context) error {
opts := telegram.TelegramOptions{
GitService: git,
CloudService: cloud,
Coda: coda,
AppConfig: c,
Controller: controller,
}
if err := telegram.Run(ctx, opts); err != nil {
return errors.Errorf("telegram bot cannot be runned: %v", err)
}
return nil
},
)
}