mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
kvdb+sqldb: update SQL error parsing to account for non wrapped errs
Some sub-systems like btcwallet will return an error from the database, but they won't properly wrap it. As a result, we were unable to actually catch the serialization errors in the first place. To work around this, we'll now attempt to parse the error string directly.
This commit is contained in:
parent
43f4b14c28
commit
329fcc6498
@ -5,6 +5,7 @@ package sqlbase
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jackc/pgconn"
|
"github.com/jackc/pgconn"
|
||||||
"github.com/jackc/pgerrcode"
|
"github.com/jackc/pgerrcode"
|
||||||
@ -13,6 +14,19 @@ import (
|
|||||||
// parsePostgresError attempts to parse a postgres error as a database agnostic
|
// parsePostgresError attempts to parse a postgres error as a database agnostic
|
||||||
// SQL error.
|
// SQL error.
|
||||||
func parsePostgresError(err error) error {
|
func parsePostgresError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sometimes the error won't be properly wrapped, so we'll need to
|
||||||
|
// inspect raw error itself to detect something we can wrap properly.
|
||||||
|
const postgresErrMsg = "could not serialize access"
|
||||||
|
if strings.Contains(err.Error(), postgresErrMsg) {
|
||||||
|
return &ErrSerializationError{
|
||||||
|
DBError: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var pqErr *pgconn.PgError
|
var pqErr *pgconn.PgError
|
||||||
if !errors.As(err, &pqErr) {
|
if !errors.As(err, &pqErr) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -5,6 +5,7 @@ package sqlbase
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"modernc.org/sqlite"
|
"modernc.org/sqlite"
|
||||||
sqlite3 "modernc.org/sqlite/lib"
|
sqlite3 "modernc.org/sqlite/lib"
|
||||||
@ -13,6 +14,21 @@ import (
|
|||||||
// parseSqliteError attempts to parse a sqlite error as a database agnostic
|
// parseSqliteError attempts to parse a sqlite error as a database agnostic
|
||||||
// SQL error.
|
// SQL error.
|
||||||
func parseSqliteError(err error) error {
|
func parseSqliteError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the error isn't wrapped properly, the errors.As call with fail,
|
||||||
|
// so we'll also try to check the expected error message directly.
|
||||||
|
// This is taken from:
|
||||||
|
// https://gitlab.com/cznic/sqlite/-/blob/v1.25.0/sqlite.go#L75.
|
||||||
|
const sqliteErrMsg = "SQLITE_BUSY"
|
||||||
|
if strings.Contains(err.Error(), sqliteErrMsg) {
|
||||||
|
return &ErrSerializationError{
|
||||||
|
DBError: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var sqliteErr *sqlite.Error
|
var sqliteErr *sqlite.Error
|
||||||
if !errors.As(err, &sqliteErr) {
|
if !errors.As(err, &sqliteErr) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -5,6 +5,7 @@ package sqldb
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jackc/pgconn"
|
"github.com/jackc/pgconn"
|
||||||
"github.com/jackc/pgerrcode"
|
"github.com/jackc/pgerrcode"
|
||||||
@ -21,6 +22,10 @@ var (
|
|||||||
// MapSQLError attempts to interpret a given error as a database agnostic SQL
|
// MapSQLError attempts to interpret a given error as a database agnostic SQL
|
||||||
// error.
|
// error.
|
||||||
func MapSQLError(err error) error {
|
func MapSQLError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to interpret the error as a sqlite error.
|
// Attempt to interpret the error as a sqlite error.
|
||||||
var sqliteErr *sqlite.Error
|
var sqliteErr *sqlite.Error
|
||||||
if errors.As(err, &sqliteErr) {
|
if errors.As(err, &sqliteErr) {
|
||||||
@ -33,6 +38,26 @@ func MapSQLError(err error) error {
|
|||||||
return parsePostgresError(pqErr)
|
return parsePostgresError(pqErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sometimes the error won't be properly wrapped, so we'll need to
|
||||||
|
// inspect raw error itself to detect something we can wrap properly.
|
||||||
|
// This handles a postgres variant of the error.
|
||||||
|
const postgresErrMsg = "could not serialize access"
|
||||||
|
if strings.Contains(err.Error(), postgresErrMsg) {
|
||||||
|
return &ErrSerializationError{
|
||||||
|
DBError: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll also attempt to catch this for sqlite, that uses a slightly
|
||||||
|
// different error message. This is taken from:
|
||||||
|
// https://gitlab.com/cznic/sqlite/-/blob/v1.25.0/sqlite.go#L75.
|
||||||
|
const sqliteErrMsg = "SQLITE_BUSY"
|
||||||
|
if strings.Contains(err.Error(), sqliteErrMsg) {
|
||||||
|
return &ErrSerializationError{
|
||||||
|
DBError: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return original error if it could not be classified as a database
|
// Return original error if it could not be classified as a database
|
||||||
// specific error.
|
// specific error.
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user