Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enhancement: Configurable database connection retries (#1926)
Allow users to configure the retry settings for establishing a database connection. This is helpful in CI environments where the database service might not be available right away. Fixes #1919 Signed-off-by: Charith Ellawala <charith@cerbos.dev> Signed-off-by: Charith Ellawala <charith@cerbos.dev>
- Loading branch information
Showing
14 changed files
with
142 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Cerbos attempts to connect to the database on startup and exits if connection cannot be established after three attempts. You can configure the connection retry settings using the `connRetry` options. | ||
|
||
`maxAttempts`:: Maximum number of connection attempts before giving up | ||
`initialInterval`:: The time to wait before the second connection attempt. Subsequent attempts have increasing wait times (exponential backoff) derived from a combination of this value and the retry attempt number | ||
`maxInterval`:: Maximum amount of time to wait between retries. This affects the maximum value produced by the exponential backoff algorithm. | ||
|
||
CAUTION: Changing the retry settings affect the availability of Cerbos and the time it takes to detect and recover from a failure. For example, if the database connection details are incorrect or have changed, it will take longer for a Cerbos PDP to fail on startup because of retries. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright 2021-2023 Zenauth Ltd. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package internal | ||
|
||
import ( | ||
"errors" | ||
"time" | ||
|
||
"github.com/cenkalti/backoff/v4" | ||
"github.com/jmoiron/sqlx" | ||
) | ||
|
||
const ( | ||
defaultRetryMaxAttempts = 3 | ||
) | ||
|
||
// ConnPoolConf holds common SQL connection pool settings. | ||
type ConnPoolConf struct { | ||
MaxLifetime time.Duration `yaml:"maxLifeTime"` | ||
MaxIdleTime time.Duration `yaml:"maxIdleTime"` | ||
MaxOpen uint `yaml:"maxOpen"` | ||
MaxIdle uint `yaml:"maxIdle"` | ||
} | ||
|
||
func (cc *ConnPoolConf) Configure(db *sqlx.DB) { | ||
if cc == nil { | ||
return | ||
} | ||
|
||
db.SetConnMaxLifetime(cc.MaxLifetime) | ||
db.SetConnMaxIdleTime(cc.MaxIdleTime) | ||
db.SetMaxIdleConns(int(cc.MaxIdle)) | ||
db.SetMaxOpenConns(int(cc.MaxOpen)) | ||
} | ||
|
||
// ConnRetryConf holds common retry settings for establishing a database connection. | ||
type ConnRetryConf struct { | ||
// MaxAttempts is the maximum number of retries to attempt before giving up. | ||
MaxAttempts uint64 `yaml:"maxAttempts"` | ||
// InitialInterval is the initial wait period between retry attempts. Subsequent attempts will be longer depending on the attempt number. | ||
InitialInterval time.Duration `yaml:"initialInterval"` | ||
// MaxInterval is the maximum amount of time to wait between retry attempts. | ||
MaxInterval time.Duration `yaml:"maxInterval"` | ||
} | ||
|
||
func (rc *ConnRetryConf) Validate() (outErr error) { | ||
if rc == nil { | ||
return nil | ||
} | ||
|
||
if rc.InitialInterval < 0 { | ||
outErr = errors.Join(outErr, errors.New("retry.initialInterval must be a positive value")) | ||
} | ||
|
||
if rc.MaxInterval < 0 { | ||
outErr = errors.Join(outErr, errors.New("retry.maxInterval must be a positive value")) | ||
} | ||
|
||
if rc.MaxInterval < rc.InitialInterval { | ||
outErr = errors.Join(outErr, errors.New("retry.maxInterval must be larger than retry.initialInterval")) | ||
} | ||
|
||
return outErr | ||
} | ||
|
||
func (rc *ConnRetryConf) BackoffConf() backoff.BackOff { | ||
if rc == nil { | ||
return backoff.WithMaxRetries(backoff.NewExponentialBackOff(), defaultRetryMaxAttempts) | ||
} | ||
|
||
b := backoff.NewExponentialBackOff() | ||
if rc.MaxInterval > 0 { | ||
b.MaxInterval = rc.MaxInterval | ||
} | ||
|
||
if rc.InitialInterval > 0 { | ||
b.InitialInterval = rc.InitialInterval | ||
} | ||
|
||
return backoff.WithMaxRetries(b, rc.MaxAttempts) | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters