diff --git a/backend/auth/jwt.go b/backend/auth/jwt.go index da59133..e3b3bc7 100644 --- a/backend/auth/jwt.go +++ b/backend/auth/jwt.go @@ -49,7 +49,7 @@ func RevokeJTI(ctx context.Context, jti string, expiresAt time.Time) error { return fmt.Errorf("revoke JTI: begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -98,10 +98,10 @@ func CleanupRevokedJTIs(ctx context.Context) (int, error) { return 0, err } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() tag, err := tx.Exec(ctx, `DELETE FROM revoked_jtis WHERE expires_at < NOW()`) @@ -208,10 +208,10 @@ func GenerateRefreshToken(ctx context.Context, userID string, role string) (stri return "", fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() var tokenID int64 err = tx.QueryRow(ctx, query, userID, token, role).Scan(&tokenID) @@ -241,10 +241,10 @@ func VerifyRefreshToken(ctx context.Context, tokenString string) (userID string, return "", "", fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() err = tx.QueryRow(ctx, query, tokenString).Scan(&userID, &role) if err != nil { diff --git a/backend/handlers/admin/custom_services.go b/backend/handlers/admin/custom_services.go index cc469aa..4c67790 100644 --- a/backend/handlers/admin/custom_services.go +++ b/backend/handlers/admin/custom_services.go @@ -395,7 +395,7 @@ func UpdateCustomService(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -433,7 +433,7 @@ func PromoteCustomService(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -543,7 +543,7 @@ func DeleteCustomService(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/admin/discount_campaigns.go b/backend/handlers/admin/discount_campaigns.go index 60a22dc..f931260 100644 --- a/backend/handlers/admin/discount_campaigns.go +++ b/backend/handlers/admin/discount_campaigns.go @@ -282,7 +282,7 @@ func CreateDiscountCampaign(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -520,7 +520,7 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -648,7 +648,7 @@ func DeleteDiscountCampaign(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/admin/patch_tests.go b/backend/handlers/admin/patch_tests.go index d6d4814..f9e605a 100644 --- a/backend/handlers/admin/patch_tests.go +++ b/backend/handlers/admin/patch_tests.go @@ -5,12 +5,14 @@ import ( "crussell/internal/validators" "database/sql" "encoding/json" + "errors" "log" "log/slog" "net/http" "strconv" "github.com/go-chi/chi/v5" + "github.com/jackc/pgx/v5" ) // PatchTest represents a patch test definition @@ -106,7 +108,7 @@ func CreatePatchTest(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -189,7 +191,7 @@ func UpdatePatchTest(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -222,7 +224,7 @@ func DeletePatchTest(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/admin/settings.go b/backend/handlers/admin/settings.go index 266cdda..1662263 100644 --- a/backend/handlers/admin/settings.go +++ b/backend/handlers/admin/settings.go @@ -3,6 +3,7 @@ package admin import ( "crussell/db" "encoding/json" + "errors" "fmt" "log" "log/slog" @@ -10,6 +11,8 @@ import ( "net/url" "strconv" "strings" + + "github.com/jackc/pgx/v5" ) type BusinessSettings struct { @@ -250,7 +253,7 @@ func UpdateBusinessSettings(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/auth/local.go b/backend/handlers/auth/local.go index 3c54b12..ef67e24 100644 --- a/backend/handlers/auth/local.go +++ b/backend/handlers/auth/local.go @@ -222,7 +222,7 @@ func RegisterHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -384,7 +384,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -433,7 +433,7 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -656,7 +656,7 @@ func VerifyCodeHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/bookings/admin_reserve.go b/backend/handlers/bookings/admin_reserve.go index fcdaee2..b184942 100644 --- a/backend/handlers/bookings/admin_reserve.go +++ b/backend/handlers/bookings/admin_reserve.go @@ -2,20 +2,21 @@ package bookings import ( "context" - "crypto/sha256" "crussell/clock" "crussell/db" "crussell/handlers/scheduling" "crussell/mw" + "crypto/sha256" "encoding/json" "errors" "fmt" - "github.com/jackc/pgx/v5" "log" "log/slog" "net" "net/http" "time" + + "github.com/jackc/pgx/v5" ) // ServiceOverrideRequest represents override values for a specific service in a reservation @@ -178,10 +179,10 @@ func AdminReserveSlotHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() // Check booking overlap inside transaction // pending_release is excluded — those bookings are evicted at creation time @@ -258,7 +259,6 @@ func AdminReserveSlotHandler(w http.ResponseWriter, r *http.Request) { TTLMinutes: req.TTLMinutes, } - w.WriteHeader(http.StatusCreated) if err := json.NewEncoder(w).Encode(response); err != nil { log.Printf("Failed to encode response: %v", err) diff --git a/backend/handlers/bookings/bookings.go b/backend/handlers/bookings/bookings.go index dcde1b1..5c2457d 100644 --- a/backend/handlers/bookings/bookings.go +++ b/backend/handlers/bookings/bookings.go @@ -22,9 +22,10 @@ import ( "strconv" "strings" - "github.com/jackc/pgx/v5" "time" + "github.com/jackc/pgx/v5" + "github.com/go-chi/chi/v5" ) @@ -1450,7 +1451,7 @@ func UpdateBookingServicesHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -2235,7 +2236,7 @@ func CreateBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -2446,7 +2447,7 @@ func EditBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -2605,7 +2606,7 @@ func ProgressBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -3034,7 +3035,7 @@ func ConfirmBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -3277,7 +3278,7 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -3370,7 +3371,7 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -4211,7 +4212,7 @@ func AdminRescheduleBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/bookings/manage.go b/backend/handlers/bookings/manage.go index 13d83eb..f9a4133 100644 --- a/backend/handlers/bookings/manage.go +++ b/backend/handlers/bookings/manage.go @@ -13,13 +13,14 @@ import ( "encoding/json" "errors" "fmt" - "github.com/jackc/pgx/v5" "log" "log/slog" "net/http" "strings" "time" + "github.com/jackc/pgx/v5" + "github.com/go-chi/chi/v5" ) @@ -44,7 +45,7 @@ func UserCancelBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -160,7 +161,7 @@ func AdminCancelBookingHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -675,7 +676,7 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1221,7 +1222,7 @@ func DeleteEditRequestHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1406,7 +1407,7 @@ func RequestEditHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1785,7 +1786,7 @@ func AdminApproveEditRequestHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -2074,7 +2075,7 @@ func AdminRejectEditRequestHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/bookings/reserve.go b/backend/handlers/bookings/reserve.go index deb0535..1771c36 100644 --- a/backend/handlers/bookings/reserve.go +++ b/backend/handlers/bookings/reserve.go @@ -3,6 +3,7 @@ package bookings import ( "crypto/sha256" "encoding/json" + "errors" "fmt" "log" "log/slog" @@ -17,6 +18,8 @@ import ( "crussell/internal/validators" "crussell/mw" "net" + + "github.com/jackc/pgx/v5" ) // ReserveSlotRequest represents the request body for reserving a slot @@ -182,7 +185,7 @@ func ReserveSlotHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -256,7 +259,7 @@ func ReserveSlotHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/notifications/notifications.go b/backend/handlers/notifications/notifications.go index ba8a322..d6e687f 100644 --- a/backend/handlers/notifications/notifications.go +++ b/backend/handlers/notifications/notifications.go @@ -6,6 +6,7 @@ import ( "crussell/internal/validators" "database/sql" "encoding/json" + "errors" "fmt" "log" "log/slog" @@ -14,6 +15,7 @@ import ( "time" "github.com/go-chi/chi/v5" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" ) @@ -245,7 +247,7 @@ func AcknowledgeNotification(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/payments/giftcards.go b/backend/handlers/payments/giftcards.go index d72cbfc..d1a29ad 100644 --- a/backend/handlers/payments/giftcards.go +++ b/backend/handlers/payments/giftcards.go @@ -363,7 +363,7 @@ func CreateGiftCard(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -472,7 +472,7 @@ func TopUpGiftCard(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -588,7 +588,7 @@ func TransferGiftCard(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -694,7 +694,7 @@ func RedeemGiftCard(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -837,7 +837,7 @@ func GetUserGiftCardBalanceAdmin(w http.ResponseWriter, r *http.Request) { log.Printf("Failed to begin transaction: %v", err) } else { defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -953,7 +953,7 @@ func BuyGiftCard(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1240,7 +1240,7 @@ func ClaimExpiredBalance(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/payments/handlers.go b/backend/handlers/payments/handlers.go index ee2de94..f987c70 100644 --- a/backend/handlers/payments/handlers.go +++ b/backend/handlers/payments/handlers.go @@ -364,7 +364,7 @@ func CreateTerminalPayment(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -646,7 +646,7 @@ func GetCheckoutStatus(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -854,7 +854,7 @@ func CreateBookingPayment(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1672,7 +1672,7 @@ func RefundPayment(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1825,7 +1825,7 @@ func CreateTipPayment(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -2030,7 +2030,7 @@ func AcquirePaymentLock(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -2083,7 +2083,7 @@ func ReleasePaymentLock(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/payments/loyalty.go b/backend/handlers/payments/loyalty.go index 15621ad..d6af1b4 100644 --- a/backend/handlers/payments/loyalty.go +++ b/backend/handlers/payments/loyalty.go @@ -98,7 +98,7 @@ func ApplyLoyaltyRedemption(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/payments/refunds.go b/backend/handlers/payments/refunds.go index 9c524e4..1950bf4 100644 --- a/backend/handlers/payments/refunds.go +++ b/backend/handlers/payments/refunds.go @@ -2,13 +2,14 @@ package payments import ( "context" + "errors" "log" "log/slog" "math" "time" - "crussell/db" "crussell/clock" + "crussell/db" "crussell/internal/square" "github.com/jackc/pgx/v5" @@ -293,10 +294,10 @@ func ProcessCancellationRefund( return &calc, nil } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() // Get the booking's user info for refund routing. var bookingUserID string @@ -562,5 +563,3 @@ func ProcessPendingSquareRefunds(ctx context.Context, bookingID string, reason s } } } - - diff --git a/backend/handlers/payments/service.go b/backend/handlers/payments/service.go index 4624a73..bb8d759 100644 --- a/backend/handlers/payments/service.go +++ b/backend/handlers/payments/service.go @@ -2,8 +2,8 @@ package payments import ( "context" - "crussell/db" "crussell/clock" + "crussell/db" "crussell/internal/square" "errors" "fmt" @@ -470,10 +470,10 @@ func (s *PaymentService) DeletePaymentMethod(ctx context.Context, cardID, userID return err } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() retainedUntil := clock.Now().Add(7 * 365 * 24 * time.Hour) _, err = tx.Exec(ctx, ` diff --git a/backend/handlers/payments/till.go b/backend/handlers/payments/till.go index 31b3df2..008f13d 100644 --- a/backend/handlers/payments/till.go +++ b/backend/handlers/payments/till.go @@ -120,7 +120,7 @@ func CreateTillSale(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -515,7 +515,7 @@ func GetTillCheckoutStatus(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/portfolio/images.go b/backend/handlers/portfolio/images.go index 9c0054f..c404794 100644 --- a/backend/handlers/portfolio/images.go +++ b/backend/handlers/portfolio/images.go @@ -24,6 +24,7 @@ import ( "time" "github.com/go-chi/chi/v5" + "github.com/jackc/pgx/v5" "github.com/kovidgoyal/imaging" ) @@ -903,7 +904,7 @@ func UploadImage(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1038,7 +1039,7 @@ func DeleteImage(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/scheduling/default-hours.go b/backend/handlers/scheduling/default-hours.go index 8bb6427..320c0fa 100644 --- a/backend/handlers/scheduling/default-hours.go +++ b/backend/handlers/scheduling/default-hours.go @@ -2,6 +2,7 @@ package scheduling import ( "encoding/json" + "errors" "fmt" "net/http" "strconv" @@ -14,6 +15,8 @@ import ( "crussell/mw" "log" "log/slog" + + "github.com/jackc/pgx/v5" ) var londonLocation = clock.London @@ -98,7 +101,7 @@ func UpdateDefaultHours(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/scheduling/exceptional-hours.go b/backend/handlers/scheduling/exceptional-hours.go index 58103b0..7ccb096 100644 --- a/backend/handlers/scheduling/exceptional-hours.go +++ b/backend/handlers/scheduling/exceptional-hours.go @@ -2,6 +2,7 @@ package scheduling import ( "encoding/json" + "errors" "log" "log/slog" "net/http" @@ -10,6 +11,8 @@ import ( "crussell/db" "crussell/internal/validators" + + "github.com/jackc/pgx/v5" ) type ExceptionalHours struct { @@ -188,7 +191,7 @@ func CreateExceptionalGroup(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -266,7 +269,7 @@ func DeleteExceptionalGroup(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -335,7 +338,7 @@ func UpdateExceptionalApplications(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/scheduling/scheduled-cleanup.go b/backend/handlers/scheduling/scheduled-cleanup.go index 0991f6e..726af0e 100644 --- a/backend/handlers/scheduling/scheduled-cleanup.go +++ b/backend/handlers/scheduling/scheduled-cleanup.go @@ -2,10 +2,13 @@ package scheduling import ( "context" + "errors" "fmt" "log/slog" "crussell/db" + + "github.com/jackc/pgx/v5" ) // NotifyUnpaidOneWeek inserts admin_notifications for bookings that ended @@ -17,10 +20,10 @@ func NotifyUnpaidOneWeek(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() rows, err := tx.Query(ctx, ` SELECT b.id, b.user_id @@ -86,10 +89,10 @@ func NotifyUnpaidOneMonth(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() rows, err := tx.Query(ctx, ` SELECT b.id, b.user_id @@ -155,10 +158,10 @@ func TransitionDiscountCampaigns(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() result, err := tx.Exec(ctx, ` UPDATE discount_campaigns @@ -201,10 +204,10 @@ func CleanupExpiredVerificationCodes(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() result, err := tx.Exec(ctx, ` DELETE FROM verification_codes @@ -230,10 +233,10 @@ func CleanupExpiredRefreshTokens(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() result, err := tx.Exec(ctx, ` DELETE FROM refresh_tokens diff --git a/backend/handlers/scheduling/time-blockers.go b/backend/handlers/scheduling/time-blockers.go index 72634ca..de3eeb4 100644 --- a/backend/handlers/scheduling/time-blockers.go +++ b/backend/handlers/scheduling/time-blockers.go @@ -3,6 +3,7 @@ package scheduling import ( "context" "encoding/json" + "errors" "fmt" "log" "log/slog" @@ -155,7 +156,7 @@ func CreateTimeBlocker(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -202,7 +203,7 @@ func DeleteTimeBlocker(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -384,7 +385,7 @@ func CleanupOldReservations(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -415,7 +416,7 @@ func AnonymizeStaleGuestAccounts(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -511,7 +512,7 @@ func CleanupExpiredLoyaltyRedemptions(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -559,7 +560,7 @@ func CleanupExpiredFinancialRecords(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -675,7 +676,7 @@ func CleanupExpiredDeposits(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -807,7 +808,7 @@ func CleanupExpiredGiftCards(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -909,7 +910,7 @@ func CleanupIdleAccounts(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1018,7 +1019,7 @@ func CleanupOldIdempotencyKeys(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1073,7 +1074,7 @@ func CleanupOldNameHistory(ctx context.Context) (int, error) { return 0, fmt.Errorf("failed to begin transaction: %w", err) } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/services/services.go b/backend/handlers/services/services.go index 17bf40b..eff5a8e 100644 --- a/backend/handlers/services/services.go +++ b/backend/handlers/services/services.go @@ -9,12 +9,13 @@ import ( "database/sql" "encoding/json" "errors" - "github.com/jackc/pgx/v5" "log" "log/slog" "net/http" "time" + "github.com/jackc/pgx/v5" + "github.com/go-chi/chi/v5" ) @@ -67,7 +68,7 @@ func ToggleService(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -147,7 +148,7 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -231,7 +232,7 @@ func DeleteServiceHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/today/today.go b/backend/handlers/today/today.go index 03bfb51..07cf8c0 100644 --- a/backend/handlers/today/today.go +++ b/backend/handlers/today/today.go @@ -13,6 +13,7 @@ import ( "crussell/clock" "crussell/db" + "github.com/jackc/pgx/v5" ) @@ -103,7 +104,7 @@ func GetCurrentAndNextHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -715,7 +716,7 @@ func GetTodayAppointmentsHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/user/account.go b/backend/handlers/user/account.go index c635dd7..ab1340c 100644 --- a/backend/handlers/user/account.go +++ b/backend/handlers/user/account.go @@ -16,6 +16,7 @@ import ( "crussell/internal/dav" "crussell/internal/s3" "crussell/mw" + "github.com/jackc/pgx/v5" ) @@ -112,10 +113,10 @@ func DeleteAccountHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() _, err = tx.Exec(ctx, `SELECT delete_guest_user($1)`, userID) if err != nil { @@ -137,10 +138,10 @@ func DeleteAccountHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(ctx); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(ctx); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() _, err = tx.Exec(ctx, `SELECT anonymize_user($1)`, userID) if err != nil { diff --git a/backend/handlers/user/guest.go b/backend/handlers/user/guest.go index 469319a..bbe7ea7 100644 --- a/backend/handlers/user/guest.go +++ b/backend/handlers/user/guest.go @@ -12,6 +12,7 @@ import ( "crussell/db" "crussell/handlers/auth" "crussell/internal/validators" + "github.com/jackc/pgx/v5" ) @@ -115,7 +116,7 @@ func CreateGuestUserHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/handlers/user/profile.go b/backend/handlers/user/profile.go index a6c6a28..2327f28 100644 --- a/backend/handlers/user/profile.go +++ b/backend/handlers/user/profile.go @@ -29,6 +29,7 @@ import ( "crussell/internal/s3" "crussell/internal/validators" "crussell/mw" + "github.com/jackc/pgx/v5" ) @@ -321,7 +322,7 @@ func UpdateProfileHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -731,7 +732,7 @@ func ChangePasswordHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -872,7 +873,7 @@ func AddPatchTestHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -969,7 +970,7 @@ func DeletePatchTestHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1084,7 +1085,7 @@ func UploadProfilePictureHandler(w http.ResponseWriter, r *http.Request) { return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() @@ -1209,7 +1210,7 @@ func UpdateNotificationPreferencesHandler(w http.ResponseWriter, r *http.Request return } defer func() { - if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" { + if err := tx.Rollback(r.Context()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { slog.Error("failed to rollback transaction", "err", err) } }() diff --git a/backend/internal/dav/shared.go b/backend/internal/dav/shared.go index 6194e66..12c3252 100644 --- a/backend/internal/dav/shared.go +++ b/backend/internal/dav/shared.go @@ -3,11 +3,13 @@ package dav import ( "context" "crussell/clock" + "errors" "fmt" "log/slog" "strings" "time" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) @@ -183,10 +185,10 @@ func (s *BaseService) CreateContact(addressBookID int, userID string, input Cont return err } defer func() { - if err := tx.Rollback(context.Background()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(context.Background()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() query := ` INSERT INTO dav_cards (addressbookid, uri, carddata, lastmodified, etag, size) @@ -217,10 +219,10 @@ func (s *BaseService) UpdateContact(addressBookID int, uri string, input Contact return err } defer func() { - if err := tx.Rollback(context.Background()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(context.Background()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() query := ` UPDATE dav_cards @@ -242,10 +244,10 @@ func (s *BaseService) DeleteContact(addressBookID int, uri string) error { return err } defer func() { - if err := tx.Rollback(context.Background()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(context.Background()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() query := `DELETE FROM dav_cards WHERE addressbookid = $1 AND uri = $2` _, err = tx.Exec(context.Background(), query, addressBookID, uri) @@ -267,10 +269,10 @@ func (s *BaseService) CreateEvent(calendarID int, input EventInput) error { return err } defer func() { - if err := tx.Rollback(context.Background()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(context.Background()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() query := ` INSERT INTO dav_calendarobjects @@ -306,10 +308,10 @@ func (s *BaseService) UpdateEvent(calendarID int, uid string, input EventInput) return err } defer func() { - if err := tx.Rollback(context.Background()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(context.Background()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() query := ` UPDATE dav_calendarobjects @@ -336,10 +338,10 @@ func (s *BaseService) DeleteEvent(calendarID int, uid string) error { return err } defer func() { - if err := tx.Rollback(context.Background()); err != nil && err.Error() != "tx is closed" { - slog.Error("failed to rollback transaction", "err", err) - } -}() + if err := tx.Rollback(context.Background()); err != nil && !errors.Is(err, pgx.ErrTxClosed) { + slog.Error("failed to rollback transaction", "err", err) + } + }() query := `DELETE FROM dav_calendarobjects WHERE calendarid = $1 AND uid = $2` _, err = tx.Exec(context.Background(), query, calendarID, uid)