mirror of
https://github.com/PrivateCaptcha/PrivateCaptcha.git
synced 2026-02-08 23:09:11 -06:00
121 lines
3.2 KiB
Go
121 lines
3.2 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"log/slog"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/billing"
|
|
"github.com/PrivateCaptcha/PrivateCaptcha/pkg/common"
|
|
config_pkg "github.com/PrivateCaptcha/PrivateCaptcha/pkg/config"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
var (
|
|
connectOnce sync.Once
|
|
globalPool *pgxpool.Pool
|
|
globalClickhouse *sql.DB
|
|
globalDBErr error
|
|
errConnectionTimeout = errors.New("connection timeout")
|
|
)
|
|
|
|
func Connect(ctx context.Context, cfg common.ConfigStore, timeout time.Duration, admin bool) (*pgxpool.Pool, *sql.DB, error) {
|
|
connectOnce.Do(func() {
|
|
globalPool, globalClickhouse, globalDBErr = connectEx(ctx, cfg, timeout, admin)
|
|
})
|
|
return globalPool, globalClickhouse, globalDBErr
|
|
}
|
|
|
|
func MigrateClickHouse(ctx context.Context, db *sql.DB, cfg common.ConfigStore, up bool) error {
|
|
if db == nil {
|
|
return nil
|
|
}
|
|
|
|
dbCfg := cfg.Get(common.ClickHouseDBKey)
|
|
const migrationsTable = "private_captcha_migrations"
|
|
|
|
return MigrateClickhouseEx(common.TraceContext(ctx, "clickhouse"), db, clickhouseMigrationsFS, dbCfg.Value(), migrationsTable, up)
|
|
}
|
|
|
|
func MigratePostgres(ctx context.Context, pool *pgxpool.Pool, cfg common.ConfigStore, planService billing.PlanService, up bool) error {
|
|
const migrationTable = "private_captcha_migrations"
|
|
|
|
migrateCtx := NewPostgresMigrateContext(ctx, cfg, planService)
|
|
tplFS := NewTemplateFS(postgresMigrationsFS, migrateCtx)
|
|
|
|
return MigratePostgresEx(common.TraceContext(ctx, "postgres"), pool, tplFS, "migrations/postgres", migrationTable, up)
|
|
}
|
|
|
|
func clickHouseUser(cfg common.ConfigStore, admin bool) string {
|
|
if admin {
|
|
if user := cfg.Get(common.ClickHouseAdminKey).Value(); len(user) > 0 {
|
|
return user
|
|
}
|
|
}
|
|
|
|
return cfg.Get(common.ClickHouseUserKey).Value()
|
|
}
|
|
|
|
func clickHousePassword(cfg common.ConfigStore, admin bool) string {
|
|
if admin {
|
|
if pwd := cfg.Get(common.ClickHouseAdminPasswordKey).Value(); len(pwd) > 0 {
|
|
return pwd
|
|
}
|
|
}
|
|
|
|
return cfg.Get(common.ClickHousePasswordKey).Value()
|
|
}
|
|
|
|
func connectEx(ctx context.Context, cfg common.ConfigStore, timeout time.Duration, admin bool) (pool *pgxpool.Pool, clickhouse *sql.DB, err error) {
|
|
errs, ctx := errgroup.WithContext(ctx)
|
|
|
|
errs.Go(func() error {
|
|
opts := ClickHouseConnectOpts{
|
|
Host: cfg.Get(common.ClickHouseHostKey).Value(),
|
|
Database: cfg.Get(common.ClickHouseDBKey).Value(),
|
|
User: clickHouseUser(cfg, admin),
|
|
Password: clickHousePassword(cfg, admin),
|
|
Port: 9000,
|
|
Verbose: config_pkg.AsBool(cfg.Get(common.VerboseKey)),
|
|
}
|
|
|
|
if opts.Empty() && config_pkg.AsBool(cfg.Get(common.ClickHouseOptionalKey)) {
|
|
slog.WarnContext(ctx, "Clickhouse connection variables are empty")
|
|
return nil
|
|
}
|
|
|
|
clickhouse = connectClickhouse(ctx, opts)
|
|
if perr := clickhouse.Ping(); perr != nil {
|
|
return perr
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
errs.Go(func() error {
|
|
config, cerr := createPgxConfig(ctx, cfg, admin)
|
|
if cerr != nil {
|
|
return cerr
|
|
}
|
|
|
|
var perr error
|
|
pool, perr = connectPostgres(ctx, config, timeout)
|
|
if perr != nil {
|
|
return perr
|
|
}
|
|
if perr := pool.Ping(ctx); perr != nil {
|
|
return perr
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
err = errs.Wait()
|
|
|
|
return
|
|
}
|