package backend import ( "fmt" "log" ) func (db *DB) WriteArticleAuthors(articleID int64, authorIDs []int64) error { query := "INSERT INTO articles_authors (article_id, author_id) VALUES (?, ?)" for i := 0; i < TxMaxRetries; i++ { err := func() error { tx, err := db.Begin() if err != nil { return fmt.Errorf("error starting transaction: %v", err) } for _, authorID := range authorIDs { if _, err := tx.Exec(query, articleID, authorID); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) } return fmt.Errorf("error inserting into articles_authors: %v", 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) wait(i) } return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries) } func (db *DB) GetArticleAuthors(c *Config, articleID int64) ([]*User, error) { query := ` SELECT u.id FROM articles a INNER JOIN articles_authors aa ON a.id = aa.article_id INNER JOIN users u ON aa.author_id = u.id WHERE a.id = ? ` rows, err := db.Query(query, articleID) if err != nil { return nil, fmt.Errorf("error querying articles_authors: %v", err) } authors := make([]*User, 0) for rows.Next() { var authorID int64 if err = rows.Scan(&authorID); err != nil { return nil, fmt.Errorf("error scanning rows: %v", err) } author, err := db.GetUser(c, authorID) if err != nil { return nil, fmt.Errorf("error getting user info for article author: %v", err) } authors = append(authors, author) } return authors, nil } func (db *DB) UpdateArticleAuthors(articleID int64, authorIDs []int64) error { deleteQuery := "DELETE FROM articles_authors WHERE article_id = ?" insertQuery := "INSERT INTO articles_authors (article_id, author_id) VALUES (?, ?)" for i := 0; i < TxMaxRetries; i++ { err := func() error { tx, err := db.Begin() if err != nil { return fmt.Errorf("error starting transaction: %v", err) } if _, err := tx.Exec(deleteQuery, articleID); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) } return fmt.Errorf("error deleting entries from articles_authors before inserting new ones: %v", err) } for _, authorID := range authorIDs { if _, err := tx.Exec(insertQuery, articleID, authorID); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { log.Fatalf("transaction error: %v, rollback error: %v", err, rollbackErr) } return fmt.Errorf("error inserting new entries into articles_authors: %v", 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) wait(i) } return fmt.Errorf("error: %v unsuccessful retries for DB operation, aborting", TxMaxRetries) }