twitch-bot/internal/actors/variables/database.go
Knut Ahlers 0d10b5165f
[core] Add retries for database access methods
to compensate for database temporarily not being available. This is not
suitable for longer database outages as 5 retries with a 1.5 multiplier
will not give much time to recover but should cover for cluster changes
and short network hickups.

Signed-off-by: Knut Ahlers <knut@ahlers.me>
2023-12-04 16:19:36 +01:00

60 lines
1.4 KiB
Go

package variables
import (
"github.com/pkg/errors"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"github.com/Luzifer/go_helpers/v2/backoff"
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
"github.com/Luzifer/twitch-bot/v3/pkg/database"
)
type (
variable struct {
Name string `gorm:"primaryKey"`
Value string
}
)
func GetVariable(db database.Connector, key string) (string, error) {
var v variable
err := helpers.Retry(func() error {
err := db.DB().First(&v, "name = ?", key).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return backoff.NewErrCannotRetry(err)
}
return err
})
switch {
case err == nil:
return v.Value, nil
case errors.Is(err, gorm.ErrRecordNotFound):
return "", nil // Compatibility to old behavior
default:
return "", errors.Wrap(err, "getting value from database")
}
}
func SetVariable(db database.Connector, key, value string) error {
return errors.Wrap(
helpers.RetryTransaction(db.DB(), func(tx *gorm.DB) error {
return tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "name"}},
DoUpdates: clause.AssignmentColumns([]string{"value"}),
}).Create(variable{Name: key, Value: value}).Error
}),
"updating value in database",
)
}
func RemoveVariable(db database.Connector, key string) error {
return errors.Wrap(
helpers.RetryTransaction(db.DB(), func(tx *gorm.DB) error {
return tx.Delete(&variable{}, "name = ?", key).Error
}),
"deleting value in database",
)
}