This commit is contained in:
@@ -2,10 +2,12 @@ package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
||||
_ "github.com/ClickHouse/clickhouse-go/v2"
|
||||
)
|
||||
|
||||
type ClickHouseConfig struct {
|
||||
@@ -15,33 +17,46 @@ type ClickHouseConfig struct {
|
||||
Database string
|
||||
}
|
||||
|
||||
func OpenClickHouse(cfg ClickHouseConfig) (driver.Conn, error) {
|
||||
conn, err := clickhouse.Open(&clickhouse.Options{
|
||||
Addr: []string{cfg.Host},
|
||||
Auth: clickhouse.Auth{
|
||||
Database: cfg.Database,
|
||||
Username: cfg.User,
|
||||
Password: cfg.Password,
|
||||
},
|
||||
Settings: clickhouse.Settings{
|
||||
"max_execution_time": 60,
|
||||
},
|
||||
Compression: &clickhouse.Compression{
|
||||
Method: clickhouse.CompressionLZ4,
|
||||
},
|
||||
DialTimeout: 30,
|
||||
MaxOpenConns: 10,
|
||||
MaxIdleConns: 5,
|
||||
ConnMaxLifetime: 3600,
|
||||
ConnOpenStrategy: clickhouse.ConnOpenInOrder,
|
||||
})
|
||||
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 connect: %w", err)
|
||||
return nil, fmt.Errorf("clickhouse open: %w", err)
|
||||
}
|
||||
|
||||
if err := conn.Ping(context.Background()); err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user