fleet/server/platform/mysql/errors.go

98 lines
2.5 KiB
Go
Raw Normal View History

package mysql
import (
"database/sql"
"errors"
"fmt"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
platform_errors "github.com/fleetdm/fleet/v4/server/platform/errors"
"github.com/go-sql-driver/mysql"
)
type NotFoundError struct {
ID uint
Name string
Message string
ResourceType string
}
// Compile-time interface check.
var _ platform_errors.NotFoundError = &NotFoundError{}
func NotFound(kind string) *NotFoundError {
return &NotFoundError{
ResourceType: kind,
}
}
func (e *NotFoundError) Error() string {
if e.ID != 0 {
return fmt.Sprintf("%s %d was not found in the datastore", e.ResourceType, e.ID)
}
if e.Name != "" {
return fmt.Sprintf("%s %s was not found in the datastore", e.ResourceType, e.Name)
}
if e.Message != "" {
return fmt.Sprintf("%s %s was not found in the datastore", e.ResourceType, e.Message)
}
return fmt.Sprintf("%s was not found in the datastore", e.ResourceType)
}
func (e *NotFoundError) WithID(id uint) error {
e.ID = id
return e
}
func (e *NotFoundError) WithName(name string) error {
e.Name = name
return e
}
func (e *NotFoundError) WithMessage(msg string) error {
e.Message = msg
return e
}
func (e *NotFoundError) IsNotFound() bool {
return true
}
// IsClientError implements ErrWithIsClientError.
func (e *NotFoundError) IsClientError() bool {
return true
}
// Is helps so that errors.Is(err, sql.ErrNoRows) returns true for an
// error of type *NotFoundError, without having to wrap sql.ErrNoRows
// explicitly.
func (e *NotFoundError) Is(other error) bool {
return other == sql.ErrNoRows
}
// MySQL error numbers for read-only conditions. These are not included in the
// VividCortex/mysqlerr package, so we define them here.
const (
// erReadOnlyTransaction is MySQL error 1792: Cannot execute statement in a READ ONLY transaction.
erReadOnlyTransaction = 1792
// erOptionPreventsStatement is MySQL error 1290: The MySQL server is running with the --read-only option.
erOptionPreventsStatement = 1290
// erReadOnlyMode is MySQL error 1836: Running in read-only mode.
erReadOnlyMode = 1836
)
// IsReadOnlyError returns true if the error is a MySQL error indicating that
// the server is in read-only mode. This typically happens after an Aurora
// failover when the primary has been demoted to a reader.
func IsReadOnlyError(err error) bool {
err = ctxerr.Cause(err)
var mySQLErr *mysql.MySQLError
if errors.As(err, &mySQLErr) {
switch mySQLErr.Number {
case erReadOnlyTransaction, erOptionPreventsStatement, erReadOnlyMode:
return true
}
}
return false
}