forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

appview/db: make NewIssue idempotent

edit if present and create if not.

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 1fe818b5 9d3f49a9

verified
Changed files
+46 -21
appview
+46 -21
appview/db/issues.go
··· 171 171 } 172 172 173 173 func NewIssue(tx *sql.Tx, issue *Issue) error { 174 - defer tx.Rollback() 175 - 174 + // ensure sequence exists 176 175 _, err := tx.Exec(` 177 176 insert or ignore into repo_issue_seqs (repo_at, next_issue_id) 178 177 values (?, 1) 179 - `, issue.RepoAt) 178 + `, issue.RepoAt) 180 179 if err != nil { 181 180 return err 182 181 } 183 182 184 - var nextId int 183 + // check if issue already exists 184 + var existingRowId, existingIssueId sql.NullInt64 185 185 err = tx.QueryRow(` 186 - update repo_issue_seqs 187 - set next_issue_id = next_issue_id + 1 188 - where repo_at = ? 189 - returning next_issue_id - 1 190 - `, issue.RepoAt).Scan(&nextId) 191 - if err != nil { 192 - return err 193 - } 186 + select rowid, issue_id from issues 187 + where did = ? and rkey = ? 188 + `, issue.Did, issue.Rkey).Scan(&existingRowId, &existingIssueId) 194 189 195 - issue.IssueId = nextId 190 + switch { 191 + case err == sql.ErrNoRows: 192 + return createNewIssue(tx, issue) 196 193 197 - res, err := tx.Exec(` 198 - insert into issues (repo_at, owner_did, rkey, issue_at, issue_id, title, body) 199 - values (?, ?, ?, ?, ?, ?, ?) 200 - `, issue.RepoAt, issue.OwnerDid, issue.Rkey, issue.AtUri(), issue.IssueId, issue.Title, issue.Body) 201 - if err != nil { 194 + case err != nil: 202 195 return err 196 + 197 + default: 198 + // Case 3: Issue exists - update it 199 + return updateIssue(tx, issue, existingRowId.Int64, int(existingIssueId.Int64)) 203 200 } 201 + } 204 202 205 - lastID, err := res.LastInsertId() 203 + func createNewIssue(tx *sql.Tx, issue *Issue) error { 204 + // get next issue_id 205 + var newIssueId int 206 + err := tx.QueryRow(` 207 + update repo_issue_seqs 208 + set next_issue_id = next_issue_id + 1 209 + where repo_at = ? 210 + returning next_issue_id - 1 211 + `, issue.RepoAt).Scan(&newIssueId) 206 212 if err != nil { 207 213 return err 208 214 } 209 - issue.ID = lastID 215 + 216 + // insert new issue 217 + row := tx.QueryRow(` 218 + insert into issues (repo_at, did, rkey, issue_id, title, body) 219 + values (?, ?, ?, ?, ?, ?) 220 + returning rowid, issue_id 221 + `, issue.RepoAt, issue.Did, issue.Rkey, newIssueId, issue.Title, issue.Body) 210 222 211 - if err := tx.Commit(); err != nil { 223 + return row.Scan(&issue.Id, &issue.IssueId) 224 + } 225 + 226 + func updateIssue(tx *sql.Tx, issue *Issue, existingRowId int64, existingIssueId int) error { 227 + // update existing issue 228 + _, err := tx.Exec(` 229 + update issues 230 + set title = ?, body = ? 231 + where did = ? and rkey = ? 232 + `, issue.Title, issue.Body, issue.Did, issue.Rkey) 233 + if err != nil { 212 234 return err 213 235 } 214 236 237 + // set the values from existing record 238 + issue.Id = existingRowId 239 + issue.IssueId = existingIssueId 215 240 return nil 216 241 } 217 242