feat(observabillity): #153 instrument sqlx
All checks were successful
Build Docker Image / Build-Docker-Image (push) Successful in 2m29s
Build and Push Docker Image / Build-And-Push-Docker-Image (push) Successful in 2m49s

This commit was merged in pull request #160.
This commit is contained in:
2025-06-07 21:55:59 +02:00
parent c4aca2778f
commit 11f3bcc89f
25 changed files with 434 additions and 409 deletions

View File

@@ -1,6 +1,7 @@
package db
import (
"context"
"database/sql"
"errors"
"log/slog"
@@ -13,23 +14,23 @@ import (
)
type Auth interface {
InsertUser(user *types.User) error
UpdateUser(user *types.User) error
GetUserByEmail(email string) (*types.User, error)
GetUser(userId uuid.UUID) (*types.User, error)
DeleteUser(userId uuid.UUID) error
InsertUser(ctx context.Context, user *types.User) error
UpdateUser(ctx context.Context, user *types.User) error
GetUserByEmail(ctx context.Context, email string) (*types.User, error)
GetUser(ctx context.Context, userId uuid.UUID) (*types.User, error)
DeleteUser(ctx context.Context, userId uuid.UUID) error
InsertToken(token *types.Token) error
GetToken(token string) (*types.Token, error)
GetTokensByUserIdAndType(userId uuid.UUID, tokenType types.TokenType) ([]*types.Token, error)
GetTokensBySessionIdAndType(sessionId string, tokenType types.TokenType) ([]*types.Token, error)
DeleteToken(token string) error
InsertToken(ctx context.Context, token *types.Token) error
GetToken(ctx context.Context, token string) (*types.Token, error)
GetTokensByUserIdAndType(ctx context.Context, userId uuid.UUID, tokenType types.TokenType) ([]*types.Token, error)
GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType types.TokenType) ([]*types.Token, error)
DeleteToken(ctx context.Context, token string) error
InsertSession(session *types.Session) error
GetSession(sessionId string) (*types.Session, error)
GetSessions(userId uuid.UUID) ([]*types.Session, error)
DeleteSession(sessionId string) error
DeleteOldSessions(userId uuid.UUID) error
InsertSession(ctx context.Context, session *types.Session) error
GetSession(ctx context.Context, sessionId string) (*types.Session, error)
GetSessions(ctx context.Context, userId uuid.UUID) ([]*types.Session, error)
DeleteSession(ctx context.Context, sessionId string) error
DeleteOldSessions(ctx context.Context, userId uuid.UUID) error
}
type AuthSqlite struct {
@@ -40,8 +41,8 @@ func NewAuthSqlite(db *sqlx.DB) *AuthSqlite {
return &AuthSqlite{db: db}
}
func (db AuthSqlite) InsertUser(user *types.User) error {
_, err := db.db.Exec(`
func (db AuthSqlite) InsertUser(ctx context.Context, user *types.User) error {
_, err := db.db.ExecContext(ctx, `
INSERT INTO user (user_id, email, email_verified, email_verified_at, is_admin, password, salt, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
user.Id, user.Email, user.EmailVerified, user.EmailVerifiedAt, user.IsAdmin, user.Password, user.Salt, user.CreateAt)
@@ -58,8 +59,8 @@ func (db AuthSqlite) InsertUser(user *types.User) error {
return nil
}
func (db AuthSqlite) UpdateUser(user *types.User) error {
_, err := db.db.Exec(`
func (db AuthSqlite) UpdateUser(ctx context.Context, user *types.User) error {
_, err := db.db.ExecContext(ctx, `
UPDATE user
SET email_verified = ?, email_verified_at = ?, password = ?
WHERE user_id = ?`,
@@ -73,7 +74,7 @@ func (db AuthSqlite) UpdateUser(user *types.User) error {
return nil
}
func (db AuthSqlite) GetUserByEmail(email string) (*types.User, error) {
func (db AuthSqlite) GetUserByEmail(ctx context.Context, email string) (*types.User, error) {
var (
userId uuid.UUID
emailVerified bool
@@ -84,7 +85,7 @@ func (db AuthSqlite) GetUserByEmail(email string) (*types.User, error) {
createdAt time.Time
)
err := db.db.QueryRow(`
err := db.db.QueryRowContext(ctx, `
SELECT user_id, email_verified, email_verified_at, password, salt, created_at
FROM user
WHERE email = ?`, email).Scan(&userId, &emailVerified, &emailVerifiedAt, &password, &salt, &createdAt)
@@ -100,7 +101,7 @@ func (db AuthSqlite) GetUserByEmail(email string) (*types.User, error) {
return types.NewUser(userId, email, emailVerified, emailVerifiedAt, isAdmin, password, salt, createdAt), nil
}
func (db AuthSqlite) GetUser(userId uuid.UUID) (*types.User, error) {
func (db AuthSqlite) GetUser(ctx context.Context, userId uuid.UUID) (*types.User, error) {
var (
email string
emailVerified bool
@@ -111,7 +112,7 @@ func (db AuthSqlite) GetUser(userId uuid.UUID) (*types.User, error) {
createdAt time.Time
)
err := db.db.QueryRow(`
err := db.db.QueryRowContext(ctx, `
SELECT email, email_verified, email_verified_at, password, salt, created_at
FROM user
WHERE user_id = ?`, userId).Scan(&email, &emailVerified, &emailVerifiedAt, &password, &salt, &createdAt)
@@ -127,49 +128,49 @@ func (db AuthSqlite) GetUser(userId uuid.UUID) (*types.User, error) {
return types.NewUser(userId, email, emailVerified, emailVerifiedAt, isAdmin, password, salt, createdAt), nil
}
func (db AuthSqlite) DeleteUser(userId uuid.UUID) error {
tx, err := db.db.Begin()
func (db AuthSqlite) DeleteUser(ctx context.Context, userId uuid.UUID) error {
tx, err := db.db.BeginTx(ctx, nil)
if err != nil {
slog.Error("Could not start transaction", "err", err)
return types.ErrInternal
}
_, err = tx.Exec("DELETE FROM account WHERE user_id = ?", userId)
_, err = tx.ExecContext(ctx, "DELETE FROM account WHERE user_id = ?", userId)
if err != nil {
_ = tx.Rollback()
slog.Error("Could not delete accounts", "err", err)
return types.ErrInternal
}
_, err = tx.Exec("DELETE FROM token WHERE user_id = ?", userId)
_, err = tx.ExecContext(ctx, "DELETE FROM token WHERE user_id = ?", userId)
if err != nil {
_ = tx.Rollback()
slog.Error("Could not delete user tokens", "err", err)
return types.ErrInternal
}
_, err = tx.Exec("DELETE FROM session WHERE user_id = ?", userId)
_, err = tx.ExecContext(ctx, "DELETE FROM session WHERE user_id = ?", userId)
if err != nil {
_ = tx.Rollback()
slog.Error("Could not delete sessions", "err", err)
return types.ErrInternal
}
_, err = tx.Exec("DELETE FROM user WHERE user_id = ?", userId)
_, err = tx.ExecContext(ctx, "DELETE FROM user WHERE user_id = ?", userId)
if err != nil {
_ = tx.Rollback()
slog.Error("Could not delete user", "err", err)
return types.ErrInternal
}
_, err = tx.Exec("DELETE FROM treasure_chest WHERE user_id = ?", userId)
_, err = tx.ExecContext(ctx, "DELETE FROM treasure_chest WHERE user_id = ?", userId)
if err != nil {
_ = tx.Rollback()
slog.Error("Could not delete user", "err", err)
return types.ErrInternal
}
_, err = tx.Exec("DELETE FROM \"transaction\" WHERE user_id = ?", userId)
_, err = tx.ExecContext(ctx, "DELETE FROM \"transaction\" WHERE user_id = ?", userId)
if err != nil {
_ = tx.Rollback()
slog.Error("Could not delete user", "err", err)
@@ -185,8 +186,8 @@ func (db AuthSqlite) DeleteUser(userId uuid.UUID) error {
return nil
}
func (db AuthSqlite) InsertToken(token *types.Token) error {
_, err := db.db.Exec(`
func (db AuthSqlite) InsertToken(ctx context.Context, token *types.Token) error {
_, err := db.db.ExecContext(ctx, `
INSERT INTO token (user_id, session_id, type, token, created_at, expires_at)
VALUES (?, ?, ?, ?, ?, ?)`, token.UserId, token.SessionId, token.Type, token.Token, token.CreatedAt, token.ExpiresAt)
@@ -198,7 +199,7 @@ func (db AuthSqlite) InsertToken(token *types.Token) error {
return nil
}
func (db AuthSqlite) GetToken(token string) (*types.Token, error) {
func (db AuthSqlite) GetToken(ctx context.Context, token string) (*types.Token, error) {
var (
userId uuid.UUID
sessionId string
@@ -209,7 +210,7 @@ func (db AuthSqlite) GetToken(token string) (*types.Token, error) {
expiresAt time.Time
)
err := db.db.QueryRow(`
err := db.db.QueryRowContext(ctx, `
SELECT user_id, session_id, type, created_at, expires_at
FROM token
WHERE token = ?`, token).Scan(&userId, &sessionId, &tokenType, &createdAtStr, &expiresAtStr)
@@ -239,8 +240,8 @@ func (db AuthSqlite) GetToken(token string) (*types.Token, error) {
return types.NewToken(userId, sessionId, token, tokenType, createdAt, expiresAt), nil
}
func (db AuthSqlite) GetTokensByUserIdAndType(userId uuid.UUID, tokenType types.TokenType) ([]*types.Token, error) {
query, err := db.db.Query(`
func (db AuthSqlite) GetTokensByUserIdAndType(ctx context.Context, userId uuid.UUID, tokenType types.TokenType) ([]*types.Token, error) {
query, err := db.db.QueryContext(ctx, `
SELECT token, created_at, expires_at
FROM token
WHERE user_id = ?
@@ -254,8 +255,8 @@ func (db AuthSqlite) GetTokensByUserIdAndType(userId uuid.UUID, tokenType types.
return getTokensFromQuery(query, userId, "", tokenType)
}
func (db AuthSqlite) GetTokensBySessionIdAndType(sessionId string, tokenType types.TokenType) ([]*types.Token, error) {
query, err := db.db.Query(`
func (db AuthSqlite) GetTokensBySessionIdAndType(ctx context.Context, sessionId string, tokenType types.TokenType) ([]*types.Token, error) {
query, err := db.db.QueryContext(ctx, `
SELECT token, created_at, expires_at
FROM token
WHERE session_id = ?
@@ -312,8 +313,8 @@ func getTokensFromQuery(query *sql.Rows, userId uuid.UUID, sessionId string, tok
return tokens, nil
}
func (db AuthSqlite) DeleteToken(token string) error {
_, err := db.db.Exec("DELETE FROM token WHERE token = ?", token)
func (db AuthSqlite) DeleteToken(ctx context.Context, token string) error {
_, err := db.db.ExecContext(ctx, "DELETE FROM token WHERE token = ?", token)
if err != nil {
slog.Error("Could not delete token", "err", err)
return types.ErrInternal
@@ -321,8 +322,8 @@ func (db AuthSqlite) DeleteToken(token string) error {
return nil
}
func (db AuthSqlite) InsertSession(session *types.Session) error {
_, err := db.db.Exec(`
func (db AuthSqlite) InsertSession(ctx context.Context, session *types.Session) error {
_, err := db.db.ExecContext(ctx, `
INSERT INTO session (session_id, user_id, created_at, expires_at)
VALUES (?, ?, ?, ?)`, session.Id, session.UserId, session.CreatedAt, session.ExpiresAt)
@@ -334,14 +335,14 @@ func (db AuthSqlite) InsertSession(session *types.Session) error {
return nil
}
func (db AuthSqlite) GetSession(sessionId string) (*types.Session, error) {
func (db AuthSqlite) GetSession(ctx context.Context, sessionId string) (*types.Session, error) {
var (
userId uuid.UUID
createdAt time.Time
expiresAt time.Time
)
err := db.db.QueryRow(`
err := db.db.QueryRowContext(ctx, `
SELECT user_id, created_at, expires_at
FROM session
WHERE session_id = ?`, sessionId).Scan(&userId, &createdAt, &expiresAt)
@@ -354,9 +355,9 @@ func (db AuthSqlite) GetSession(sessionId string) (*types.Session, error) {
return types.NewSession(sessionId, userId, createdAt, expiresAt), nil
}
func (db AuthSqlite) GetSessions(userId uuid.UUID) ([]*types.Session, error) {
func (db AuthSqlite) GetSessions(ctx context.Context, userId uuid.UUID) ([]*types.Session, error) {
var sessions []*types.Session
err := db.db.Select(&sessions, `
err := db.db.SelectContext(ctx, &sessions, `
SELECT *
FROM session
WHERE user_id = ?`, userId)
@@ -368,8 +369,8 @@ func (db AuthSqlite) GetSessions(userId uuid.UUID) ([]*types.Session, error) {
return sessions, nil
}
func (db AuthSqlite) DeleteOldSessions(userId uuid.UUID) error {
_, err := db.db.Exec(`
func (db AuthSqlite) DeleteOldSessions(ctx context.Context, userId uuid.UUID) error {
_, err := db.db.ExecContext(ctx, `
DELETE FROM session
WHERE expires_at < datetime('now')
AND user_id = ?`, userId)
@@ -380,9 +381,9 @@ func (db AuthSqlite) DeleteOldSessions(userId uuid.UUID) error {
return nil
}
func (db AuthSqlite) DeleteSession(sessionId string) error {
func (db AuthSqlite) DeleteSession(ctx context.Context, sessionId string) error {
if sessionId != "" {
_, err := db.db.Exec("DELETE FROM session WHERE session_id = ?", sessionId)
_, err := db.db.ExecContext(ctx, "DELETE FROM session WHERE session_id = ?", sessionId)
if err != nil {
slog.Error("Could not delete session", "err", err)
return types.ErrInternal

View File

@@ -1,6 +1,7 @@
package db
import (
"context"
"errors"
"log/slog"
"spend-sparrow/internal/types"
@@ -20,7 +21,7 @@ func (l migrationLogger) Verbose() bool {
return false
}
func RunMigrations(db *sqlx.DB, pathPrefix string) error {
func RunMigrations(ctx context.Context, db *sqlx.DB, pathPrefix string) error {
driver, err := sqlite3.WithInstance(db.DB, &sqlite3.Config{})
if err != nil {
slog.Error("Could not create Migration instance", "err", err)