package main import ( "context" "flag" "fmt" "log" "os" "os/signal" "syscall" "ticket-pimp/internal/controller" "ticket-pimp/internal/domain" "ticket-pimp/internal/services" "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) { // Aply 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) db.Close() } func run(conf *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", conf.DB.User, conf.DB.Pass, conf.DB.Host, conf.DB.Port, conf.DB.Name, ) conn, err := pgxpool.New( ctx, connString) if err != nil { log.Fatalf("DB connection failed: %v", err) } // -- DB connection init -- END // Aply migrations: applyMigrations(connString) // Init services instances: gitService := services.NewGit(conf.Git) cloudService := services.NewCloud(conf.Cloud) codaService := services.NewCodaClient(conf.Coda) // Controller instance init: controller := controller.NewWorkflowController( gitService, cloudService, codaService, conn, conf, ) Go(ctx, func(ctx context.Context) error { opts := discord.DiscordOptions{ Controller: controller, Config: conf, } if err := discord.Run(conf, opts); err != nil { return errors.Errorf("discord bot cannot be runned: %v", err) } return nil }, func(ctx context.Context) error { opts := telegram.TelegramOptions{ GitService: gitService, CloudService: cloudService, Coda: codaService, AppConfig: conf, Controller: controller, } if err := telegram.Run(ctx, opts); err != nil { return errors.Errorf("telegram bot cannot be runned: %v", err) } return nil }, ) }