Use a more general db client factory approach.

This commit is contained in:
Sascha L. Teichmann 2022-03-01 14:47:14 +01:00
parent 834c8a9bc6
commit c507663826
9 changed files with 99 additions and 53 deletions

View File

@ -56,7 +56,7 @@ func createTiles(
} }
func createBaseLevel( func createBaseLevel(
dbcc common.DBClientCreator, dbcf common.DBClientFactory,
xMin, yMin, zMin, xMax, yMax, zMax int, xMin, yMin, zMin, xMax, yMax, zMax int,
transparent bool, transparentDim float32, transparent bool, transparentDim float32,
colorsFile string, bg color.RGBA, outDir string, colorsFile string, bg color.RGBA, outDir string,
@ -81,7 +81,7 @@ func createBaseLevel(
for i := 0; i < numWorkers; i++ { for i := 0; i < numWorkers; i++ {
var client common.DBClient var client common.DBClient
if client, err = dbcc(); err != nil { if client, err = dbcf.Create(); err != nil {
return return
} }
done.Add(1) done.Add(1)

View File

@ -68,12 +68,16 @@ func main() {
bg := common.ParseColorDefault(bgColor, common.BackgroundColor) bg := common.ParseColorDefault(bgColor, common.BackgroundColor)
dbcc := common.CreateDBClientCreator(host, port) dbcf, err := common.CreateDBClientFactory(host, port)
if err != nil {
log.Fatalf("error: %s\n", err)
}
defer dbcf.Close()
if !skipBaseLevel { if !skipBaseLevel {
td := common.Clamp32f(float32(transparentDim/100.0), 0.0, 1.0) td := common.Clamp32f(float32(transparentDim/100.0), 0.0, 1.0)
if err := createBaseLevel( if err := createBaseLevel(
dbcc, dbcf,
xMin, yMin, zMin, xMax, yMax, zMax, xMin, yMin, zMin, xMax, yMax, zMax,
transparent, td, transparent, td,
colorsFile, bg, colorsFile, bg,

View File

@ -83,7 +83,12 @@ func main() {
colors.TransparentDim = common.Clamp32f( colors.TransparentDim = common.Clamp32f(
float32(transparentDim/100.0), 0.0, 100.0) float32(transparentDim/100.0), 0.0, 100.0)
client, err := common.CreateDBClientCreator(host, port)() cf, err := common.CreateDBClientFactory(host, port)
if err != nil {
log.Fatalf("error: %v\n", err)
}
client, err := cf.Create()
if err != nil { if err != nil {
log.Fatalf("Cannot connect to '%s:%d': %s", host, port, err) log.Fatalf("Cannot connect to '%s:%d': %s", host, port, err)
} }

View File

@ -118,7 +118,11 @@ func main() {
colors.TransparentDim = common.Clamp32f( colors.TransparentDim = common.Clamp32f(
float32(transparentDim/100.0), 0.0, 100.0) float32(transparentDim/100.0), 0.0, 100.0)
dbcc := common.CreateDBClientCreator(redisHost, redisPort) dbcf, err := common.CreateDBClientFactory(redisHost, redisPort)
if err != nil {
log.Fatalf("error: %v\n", err)
}
defer dbcf.Close()
var allowedUpdateIps []net.IP var allowedUpdateIps []net.IP
if allowedUpdateIps, err = ipsFromHosts(updateHosts); err != nil { if allowedUpdateIps, err = ipsFromHosts(updateHosts); err != nil {
@ -127,7 +131,7 @@ func main() {
tu := newTileUpdater( tu := newTileUpdater(
mapDir, mapDir,
dbcc, dbcf,
allowedUpdateIps, allowedUpdateIps,
colors, bg, colors, bg,
yMin, yMax, yMin, yMax,

View File

@ -38,7 +38,7 @@ type tileUpdater struct {
changes map[xz]struct{} changes map[xz]struct{}
btu baseTilesUpdates btu baseTilesUpdates
mapDir string mapDir string
dbcc common.DBClientCreator dbcf common.DBClientFactory
ips []net.IP ips []net.IP
colors *common.Colors colors *common.Colors
bg color.RGBA bg color.RGBA
@ -82,7 +82,7 @@ func (c xz) parent() xzm {
func newTileUpdater( func newTileUpdater(
mapDir string, mapDir string,
dbcc common.DBClientCreator, dbcf common.DBClientFactory,
ips []net.IP, ips []net.IP,
colors *common.Colors, colors *common.Colors,
bg color.RGBA, bg color.RGBA,
@ -94,7 +94,7 @@ func newTileUpdater(
tu := tileUpdater{ tu := tileUpdater{
btu: btu, btu: btu,
mapDir: mapDir, mapDir: mapDir,
dbcc: dbcc, dbcf: dbcf,
ips: ips, ips: ips,
changes: map[xz]struct{}{}, changes: map[xz]struct{}{},
colors: colors, colors: colors,
@ -262,10 +262,11 @@ func (tu *tileUpdater) doUpdates() {
for i, n := 0, common.Min(tu.workers, len(changes)); i < n; i++ { for i, n := 0, common.Min(tu.workers, len(changes)); i < n; i++ {
var client common.DBClient var client common.DBClient
var err error var err error
if client, err = tu.dbcc(); err != nil { if client, err = tu.dbcf.Create(); err != nil {
log.Printf("WARN: Cannot connect to redis server: %s\n", err) log.Printf("WARN: Cannot connect to redis server: %s\n", err)
continue continue
} }
btc := common.NewBaseTileCreator( btc := common.NewBaseTileCreator(
client, tu.colors, tu.bg, client, tu.colors, tu.bg,
tu.yMin, tu.yMax, tu.yMin, tu.yMax,

View File

@ -5,11 +5,18 @@
package common package common
import ( import (
"fmt"
"strings" "strings"
) )
type DBClientCreator func() (DBClient, error) type DBClient interface {
QueryCuboid(cuboid Cuboid, fn func(*Block) *Block) (count int, err error)
Close() error
}
type DBClientFactory interface {
Create() (DBClient, error)
Close() error
}
func IsPostgreSQL(host string) (string, bool) { func IsPostgreSQL(host string) (string, bool) {
if strings.HasPrefix(host, "postgres:") { if strings.HasPrefix(host, "postgres:") {
@ -18,29 +25,11 @@ func IsPostgreSQL(host string) (string, bool) {
return "", false return "", false
} }
func CreateDBClientCreator(host string, port int) DBClientCreator { func CreateDBClientFactory(host string, port int) (DBClientFactory, error) {
if host, ok := IsPostgreSQL(host); ok { if connS, ok := IsPostgreSQL(host); ok {
return func() (DBClient, error) { return NewPGClientFactory(connS)
return NewPGClient(host)
}
} }
var address string return NewRedisClientFactory(host, port)
if strings.ContainsRune(host, '/') {
address = host
} else {
address = fmt.Sprintf("%s:%d", host, port)
}
var proto string
if strings.ContainsRune(address, '/') {
proto = "unix"
} else {
proto = "tcp"
}
return func() (DBClient, error) {
return NewRedisClient(proto, address)
}
} }

View File

@ -1,10 +0,0 @@
// Copyright 2022 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package common
type DBClient interface {
QueryCuboid(cuboid Cuboid, fn func(*Block) *Block) (count int, err error)
Close() error
}

View File

@ -19,24 +19,43 @@ WHERE
posz BETWEEN $5 AND $6` posz BETWEEN $5 AND $6`
type PGClient struct { type PGClient struct {
db *sql.DB conn *sql.Conn
queryCuboidStmt *sql.Stmt queryCuboidStmt *sql.Stmt
} }
func NewPGClient(connS string) (*PGClient, error) { type PGClientFactory struct {
db *sql.DB
}
func NewPGClientFactory(connS string) (*PGClientFactory, error) {
db, err := sql.Open("pgx", connS) db, err := sql.Open("pgx", connS)
if err != nil { if err != nil {
return nil, err return nil, err
} }
stmt, err := db.Prepare(queryCuboidSQL) return &PGClientFactory{db: db}, nil
}
func (pgcf *PGClientFactory) Close() error {
return pgcf.db.Close()
}
func (pgcf *PGClientFactory) Create() (DBClient, error) {
ctx := context.Background()
conn, err := pgcf.db.Conn(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
client := PGClient{ stmt, err := conn.PrepareContext(ctx, queryCuboidSQL)
db: db, if err != nil {
queryCuboidStmt: stmt, conn.Close()
return nil, err
} }
return &client, nil return &PGClient{
conn: conn,
queryCuboidStmt: stmt,
}, nil
} }
func (pgc *PGClient) QueryCuboid( func (pgc *PGClient) QueryCuboid(
@ -94,5 +113,5 @@ func (pgc *PGClient) Close() error {
if pgc.queryCuboidStmt != nil { if pgc.queryCuboidStmt != nil {
pgc.queryCuboidStmt.Close() pgc.queryCuboidStmt.Close()
} }
return pgc.db.Close() return pgc.conn.Close()
} }

View File

@ -11,9 +11,43 @@ import (
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
"strings"
"unicode" "unicode"
) )
type RedisClientFactory struct {
proto string
address string
}
func NewRedisClientFactory(host string, port int) (*RedisClientFactory, error) {
var address string
if strings.ContainsRune(host, '/') {
address = host
} else {
address = fmt.Sprintf("%s:%d", host, port)
}
var proto string
if strings.ContainsRune(address, '/') {
proto = "unix"
} else {
proto = "tcp"
}
return &RedisClientFactory{
proto: proto,
address: address,
}, nil
}
func (rcf *RedisClientFactory) Close() error {
return nil
}
func (rcf *RedisClientFactory) Create() (DBClient, error) {
return NewRedisClient(rcf.proto, rcf.address)
}
type RedisClient struct { type RedisClient struct {
conn net.Conn conn net.Conn
reader *bufio.Reader reader *bufio.Reader