diff --git a/cmd/model/articles.go b/cmd/model/articles.go index 43e0e50..38737a9 100644 --- a/cmd/model/articles.go +++ b/cmd/model/articles.go @@ -20,8 +20,7 @@ func (db *DB) AddArticle(a *Article) (int64, error) { query := ` INSERT INTO articles (title, description, content, published, rejected, author_id) - VALUES - (?, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?) ` result, err := db.Exec(query, a.Title, a.Description, a.Content, a.Published, diff --git a/cmd/model/db.go b/cmd/model/db.go index e67b7a3..4720b5b 100644 --- a/cmd/model/db.go +++ b/cmd/model/db.go @@ -5,14 +5,19 @@ import ( "database/sql" "fmt" "log" + "math" + "math/rand/v2" "os" "strings" "syscall" + "time" "github.com/go-sql-driver/mysql" "golang.org/x/term" ) +var TxMaxRetries = 3 + type DB struct { *sql.DB } @@ -92,29 +97,42 @@ func OpenDB(dbName string) (*DB, error) { } func (db *DB) UpdateAttributes(a ...*Attribute) error { - tx, err := db.Begin() - if err != nil { - return fmt.Errorf("error starting transaction: %v", err) - } - - for _, attribute := range a { - query := fmt.Sprintf(` - UPDATE %s - SET %s = ? - WHERE id = ? - `, attribute.Table, attribute.AttName) - if _, err := tx.Exec(query, attribute.Value, attribute.ID); err != nil { - if rollbackErr := tx.Rollback(); rollbackErr != nil { - log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) + for i := 0; i < TxMaxRetries; i++ { + err := func() error { + tx, err := db.Begin() + if err != nil { + return fmt.Errorf("error starting transaction: %v", err) } - return fmt.Errorf("error updating %v in DB: %v", attribute.AttName, err) - } - } - if err = tx.Commit(); err != nil { - return fmt.Errorf("error committing transaction: %v", err) + for _, attribute := range a { + query := fmt.Sprintf(` + UPDATE %s + SET %s = ? + WHERE id = ? + `, attribute.Table, attribute.AttName) + if _, err := tx.Exec(query, attribute.Value, attribute.ID); err != nil { + if rollbackErr := tx.Rollback(); rollbackErr != nil { + log.Fatalf("error: transaction error: %v, rollback error: %v", err, rollbackErr) + } + return fmt.Errorf("error updating %v in DB: %v", attribute.AttName, err) + } + } + + if err = tx.Commit(); err != nil { + return fmt.Errorf("error committing transaction: %v", err) + } + return nil + }() + if err == nil { + return nil + } + log.Println(err) + + waitTime := time.Duration(math.Pow(2, float64(i))) * time.Second + jitter := time.Duration(rand.IntN(1000)) * time.Millisecond + time.Sleep(waitTime + jitter) } - return nil + return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries) } func (db *DB) CountEntries(table string) (int64, error) { diff --git a/cmd/model/users.go b/cmd/model/users.go index f0b2802..d5d45f3 100644 --- a/cmd/model/users.go +++ b/cmd/model/users.go @@ -28,8 +28,7 @@ func (db *DB) AddUser(user *User, pass string) error { } query := ` - INSERT INTO users - (username, password, first_name, last_name, role) + INSERT INTO users (username, password, first_name, last_name, role) VALUES (?, ?, ?, ?, ?) ` if _, err = db.Exec(query, user.UserName, string(hashedPass), user.FirstName, user.LastName, user.Role); err != nil {