mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 23:57:31 +00:00
fix(db): add additional connection pool for projection spooling (#7094)
* fix(db): add additional connection pool for projection spooling * use correct connection pool for projections --------- Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
@@ -1,43 +1,90 @@
|
||||
package dialect
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ConnectionInfo struct {
|
||||
EventstorePusher ConnectionConfig
|
||||
ZITADEL ConnectionConfig
|
||||
}
|
||||
var (
|
||||
ErrNegativeRatio = errors.New("ratio cannot be negative")
|
||||
ErrHighSumRatio = errors.New("sum of pusher and projection ratios must be < 1")
|
||||
ErrIllegalMaxOpenConns = errors.New("MaxOpenConns of the database must be higher than 3 or 0 for unlimited")
|
||||
ErrIllegalMaxIdleConns = errors.New("MaxIdleConns of the database must be higher than 3 or 0 for unlimited")
|
||||
ErrInvalidPurpose = errors.New("DBPurpose out of range")
|
||||
)
|
||||
|
||||
// ConnectionConfig defines the Max Open and Idle connections for a DB connection pool.
|
||||
type ConnectionConfig struct {
|
||||
MaxOpenConns,
|
||||
MaxIdleConns uint32
|
||||
}
|
||||
|
||||
func NewConnectionInfo(openConns, idleConns uint32, pusherRatio float64) (*ConnectionInfo, error) {
|
||||
if pusherRatio < 0 || pusherRatio > 1 {
|
||||
return nil, errors.New("EventPushConnRatio must be between 0 and 1")
|
||||
}
|
||||
if openConns != 0 && openConns < 2 {
|
||||
return nil, errors.New("MaxOpenConns of the database must be higher that 1")
|
||||
// takeRatio of MaxOpenConns and MaxIdleConns from config and returns
|
||||
// a new ConnectionConfig with the resulting values.
|
||||
func (c *ConnectionConfig) takeRatio(ratio float64) (*ConnectionConfig, error) {
|
||||
if ratio < 0 {
|
||||
return nil, ErrNegativeRatio
|
||||
}
|
||||
|
||||
info := new(ConnectionInfo)
|
||||
|
||||
info.EventstorePusher.MaxOpenConns = uint32(pusherRatio * float64(openConns))
|
||||
info.EventstorePusher.MaxIdleConns = uint32(pusherRatio * float64(idleConns))
|
||||
|
||||
if openConns != 0 && info.EventstorePusher.MaxOpenConns < 1 && pusherRatio > 0 {
|
||||
info.EventstorePusher.MaxOpenConns = 1
|
||||
out := &ConnectionConfig{
|
||||
MaxOpenConns: uint32(ratio * float64(c.MaxOpenConns)),
|
||||
MaxIdleConns: uint32(ratio * float64(c.MaxIdleConns)),
|
||||
}
|
||||
if idleConns != 0 && info.EventstorePusher.MaxIdleConns < 1 && pusherRatio > 0 {
|
||||
info.EventstorePusher.MaxIdleConns = 1
|
||||
if c.MaxOpenConns != 0 && out.MaxOpenConns < 1 && ratio > 0 {
|
||||
out.MaxOpenConns = 1
|
||||
}
|
||||
if c.MaxIdleConns != 0 && out.MaxIdleConns < 1 && ratio > 0 {
|
||||
out.MaxIdleConns = 1
|
||||
}
|
||||
|
||||
if openConns != 0 {
|
||||
info.ZITADEL.MaxOpenConns = openConns - info.EventstorePusher.MaxOpenConns
|
||||
}
|
||||
if idleConns != 0 {
|
||||
info.ZITADEL.MaxIdleConns = idleConns - info.EventstorePusher.MaxIdleConns
|
||||
}
|
||||
|
||||
return info, nil
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// NewConnectionConfig calculates [ConnectionConfig] values from the passed ratios
|
||||
// and returns the config applicable for the requested purpose.
|
||||
//
|
||||
// openConns and idleConns must be at least 3 or 0, which means no limit.
|
||||
// The pusherRatio and spoolerRatio must be between 0 and 1.
|
||||
func NewConnectionConfig(openConns, idleConns uint32, pusherRatio, projectionRatio float64, purpose DBPurpose) (*ConnectionConfig, error) {
|
||||
if openConns != 0 && openConns < 3 {
|
||||
return nil, ErrIllegalMaxOpenConns
|
||||
}
|
||||
if idleConns != 0 && idleConns < 3 {
|
||||
return nil, ErrIllegalMaxIdleConns
|
||||
}
|
||||
if pusherRatio+projectionRatio >= 1 {
|
||||
return nil, ErrHighSumRatio
|
||||
}
|
||||
|
||||
queryConfig := &ConnectionConfig{
|
||||
MaxOpenConns: openConns,
|
||||
MaxIdleConns: idleConns,
|
||||
}
|
||||
pusherConfig, err := queryConfig.takeRatio(pusherRatio)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("event pusher: %w", err)
|
||||
}
|
||||
spoolerConfig, err := queryConfig.takeRatio(projectionRatio)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("projection spooler: %w", err)
|
||||
}
|
||||
|
||||
// subtract the claimed amount
|
||||
if queryConfig.MaxOpenConns > 0 {
|
||||
queryConfig.MaxOpenConns -= pusherConfig.MaxOpenConns + spoolerConfig.MaxOpenConns
|
||||
}
|
||||
if queryConfig.MaxIdleConns > 0 {
|
||||
queryConfig.MaxIdleConns -= pusherConfig.MaxIdleConns + spoolerConfig.MaxIdleConns
|
||||
}
|
||||
|
||||
switch purpose {
|
||||
case DBPurposeQuery:
|
||||
return queryConfig, nil
|
||||
case DBPurposeEventPusher:
|
||||
return pusherConfig, nil
|
||||
case DBPurposeProjectionSpooler:
|
||||
return spoolerConfig, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: %v", ErrInvalidPurpose, purpose)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user