Files
HellreigN/backend/internal/storage/clickhouse.go
T
d3m0k1d 0f8b148279
ci-agent / build (push) Failing after 2m50s
fix: linter and docs
2026-04-04 19:44:16 +03:00

77 lines
1.5 KiB
Go

package storage
import (
"context"
"database/sql"
"fmt"
"log"
"time"
_ "github.com/ClickHouse/clickhouse-go/v2"
)
type ClickHouseConfig struct {
Host string
User string
Password string
Database string
}
func OpenClickHouse(cfg ClickHouseConfig) (*sql.DB, error) {
dsn := fmt.Sprintf("clickhouse://%s:%s@%s/%s",
cfg.User, cfg.Password, cfg.Host, cfg.Database)
db, err := sql.Open("clickhouse", dsn)
if err != nil {
return nil, fmt.Errorf("clickhouse open: %w", err)
}
db.SetMaxOpenConns(5)
db.SetMaxIdleConns(2)
db.SetConnMaxLifetime(10 * time.Minute)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := db.PingContext(ctx); err != nil {
db.Close()
return nil, fmt.Errorf("clickhouse ping: %w", err)
}
log.Printf("ClickHouse connected via database/sql: %s", cfg.Host)
return db, nil
}
// OpenClickHouseWithRetry attempts to connect to ClickHouse with retries and backoff.
func OpenClickHouseWithRetry(
cfg ClickHouseConfig,
maxRetries int,
initialDelay time.Duration,
) (*sql.DB, error) {
var lastErr error
delay := initialDelay
for i := 0; i < maxRetries; i++ {
db, err := OpenClickHouse(cfg)
if err == nil {
return db, nil
}
lastErr = err
log.Printf(
"ClickHouse connection attempt %d/%d failed: %v, retrying in %v...",
i+1,
maxRetries,
err,
delay,
)
time.Sleep(delay)
delay *= 2
}
return nil, fmt.Errorf(
"clickhouse connection failed after %d attempts: %w",
maxRetries,
lastErr,
)
}