package backend import ( "context" "database/sql" "fmt" "log" ) func (db *DB) AddIssue() (int64, error) { query := "INSERT INTO issues (published) VALUES (?)" result, err := db.Exec(query, false) if err != nil { return 0, fmt.Errorf("error inserting issue into DB: %v", err) } id, err := result.LastInsertId() if err != nil { return 0, fmt.Errorf("error getting ID of added issue: %v", err) } return id, nil } func (db *DB) PublishLatestIssue() error { txOptions := &sql.TxOptions{Isolation: sql.LevelSerializable} updateQuery := "UPDATE issues SET published = true WHERE published = false" insertQuery := "INSERT INTO issues (published) VALUES (?)" for i := 0; i < TxMaxRetries; i++ { err := func() error { tx, err := db.BeginTx(context.Background(), txOptions) if err != nil { return fmt.Errorf("error starting transaction: %v", err) } if _, err := tx.Exec(updateQuery); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) } return fmt.Errorf("error publishing issue: %v", err) } if _, err := tx.Exec(insertQuery, false); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) } return fmt.Errorf("error inserting new issue into DB: %v", err) } if err = tx.Commit(); err != nil { return fmt.Errorf("error committing transaction when publishing issue: %v", err) } return nil }() if err == nil { return nil } log.Println(err) wait(i) } return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries) }