package dal import ( "context" "database/sql" _ "embed" "errors" "fmt" _ "github.com/ClickHouse/clickhouse-go" _ "github.com/lib/pq" "github.com/minio/minio-go/v7" "gitea.pena/SQuiz/common/dal/sqlcgen" "gitea.pena/SQuiz/common/repository/account" "gitea.pena/SQuiz/common/repository/amo" "gitea.pena/SQuiz/common/repository/answer" "gitea.pena/SQuiz/common/repository/question" "gitea.pena/SQuiz/common/repository/quiz" "gitea.pena/SQuiz/common/repository/result" "gitea.pena/SQuiz/common/repository/statistics" "gitea.pena/SQuiz/common/repository/tg" "gitea.pena/SQuiz/common/repository/workers" "time" ) var errNextDeclined = errors.New("next is declined") type DAL struct { conn *sql.DB queries *sqlcgen.Queries AccountRepo *account.AccountRepository AnswerRepo *answer.AnswerRepository QuestionRepo *question.QuestionRepository QuizRepo *quiz.QuizRepository ResultRepo *result.ResultRepository WorkerRepo *workers.WorkerRepository StatisticsRepo *statistics.StatisticsRepository WorkerAnsRepo *answer.WorkerAnswerRepository TgRepo *tg.TgRepo } func New(ctx context.Context, cred string, minioClient *minio.Client) (*DAL, error) { pool, err := sql.Open("postgres", cred) if err != nil { return nil, err } timeoutCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() if err := pool.PingContext(timeoutCtx); err != nil { return nil, err } queries := sqlcgen.New(pool) accountRepo := account.NewAccountRepository(account.Deps{ Queries: queries, Pool: pool, }) storerAnswer := &answer.StorerAnswer{} if minioClient != nil { storerAnswer, err = answer.NewAnswerMinio(ctx, minioClient) if err != nil { return nil, err } } workerAnsRepo := answer.NewWorkerAnswerRepo(answer.Deps{ Queries: queries, Pool: pool, AnswerMinio: storerAnswer, }) answerRepo := answer.NewAnswerRepository(answer.Deps{ Queries: queries, Pool: pool, }) questionRepo := question.NewQuestionRepository(question.Deps{ Queries: queries, Pool: pool, }) quizRepo := quiz.NewQuizRepository(quiz.Deps{ Queries: queries, Pool: pool, }) resultRepo := result.NewResultRepository(result.Deps{ Queries: queries, Pool: pool, }) workerRepo := workers.NewWorkerRepository(workers.Deps{ Queries: queries, }) statisticsRepo := statistics.NewStatisticsRepo(statistics.Deps{ Queries: queries, Pool: pool, }) tgRepo := tg.NewTgRepo(tg.Deps{ Queries: queries, Pool: pool, }) return &DAL{ conn: pool, queries: queries, AccountRepo: accountRepo, AnswerRepo: answerRepo, QuestionRepo: questionRepo, QuizRepo: quizRepo, ResultRepo: resultRepo, WorkerRepo: workerRepo, StatisticsRepo: statisticsRepo, WorkerAnsRepo: workerAnsRepo, TgRepo: tgRepo, }, nil } func (d *DAL) Close(ctx context.Context) error { err := d.conn.Close() if err != nil { return err } return nil } type AmoDal struct { conn *sql.DB queries *sqlcgen.Queries AmoRepo *amo.AmoRepository QuestionRepo *question.QuestionRepository AnswerRepo *answer.AnswerRepository QuizRepo *quiz.QuizRepository AccountRepo *account.AccountRepository } func NewAmoDal(ctx context.Context, cred string) (*AmoDal, error) { pool, err := sql.Open("postgres", cred) if err != nil { return nil, err } timeoutCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() if err := pool.PingContext(timeoutCtx); err != nil { return nil, err } queries := sqlcgen.New(pool) amoRepo := amo.NewAmoRepository(amo.Deps{ Queries: queries, Pool: pool, }) questionRepo := question.NewQuestionRepository(question.Deps{ Queries: queries, Pool: pool, }) answerRepo := answer.NewAnswerRepository(answer.Deps{ Queries: queries, Pool: pool, }) quizRepo := quiz.NewQuizRepository(quiz.Deps{ Queries: queries, Pool: pool, }) accountRepo := account.NewAccountRepository(account.Deps{ Queries: queries, Pool: pool, }) return &AmoDal{ conn: pool, queries: queries, AmoRepo: amoRepo, QuestionRepo: questionRepo, AnswerRepo: answerRepo, QuizRepo: quizRepo, AccountRepo: accountRepo, }, nil } func (d *AmoDal) Close(ctx context.Context) error { err := d.conn.Close() if err != nil { return err } return nil } type ClickHouseDAL struct { conn *sql.DB StatisticClickRepo *statistics.StatisticClick } func NewClickHouseDAL(ctx context.Context, cred string) (*ClickHouseDAL, error) { conn, err := sql.Open("clickhouse", cred) if err != nil { return nil, fmt.Errorf("error open database connection: %w", err) } timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() if err := conn.PingContext(timeoutCtx); err != nil { return nil, fmt.Errorf("error ping database: %w", err) } statsClickRepo, err := statistics.NewClickStatistic(ctx, statistics.DepsClick{ Conn: conn, }) if err != nil { return nil, err } return &ClickHouseDAL{ conn: conn, StatisticClickRepo: statsClickRepo, }, nil } func (d *ClickHouseDAL) Close(ctx context.Context) error { return d.conn.Close() }