appview: db: replace Issue.IssueAt to Issue.Rkey #498

merged
opened by boltless.me targeting master from boltless.me/core: push-pltwsolxxvnt

Replace Issue.IssueAt to Issue.Rkey. issue_at column still exist, but not used and will be removed in future.

Remove db.SetIssueAt() in flavor of Rkey. Create rkey before adding to DB, and save same rkey to PDS. This is safe as tx is will be dropped when ctx is canceled with error.

Signed-off-by: Seongmin Lee boltlessengineer@proton.me

Changed files
+39 -30
appview
db
issues
pages
templates
repo
issues
+11
appview/db/db.go
··· 663 return err 664 }) 665 666 return &DB{db}, nil 667 } 668
··· 663 return err 664 }) 665 666 + runMigration(db, "add-rkey-to-issues", func(tx *sql.Tx) error { 667 + _, err := tx.Exec(` 668 + alter table issues add column rkey text not null default ''; 669 + 670 + -- get last url section from issue_at and save to rkey column 671 + update issues 672 + set rkey = replace(issue_at, rtrim(issue_at, replace(issue_at, '/', '')), ''); 673 + `) 674 + return err 675 + }) 676 + 677 return &DB{db}, nil 678 } 679
+19 -14
appview/db/issues.go
··· 2 3 import ( 4 "database/sql" 5 "time" 6 7 "github.com/bluesky-social/indigo/atproto/syntax" 8 "tangled.sh/tangled.sh/core/appview/pagination" 9 ) 10 ··· 13 RepoAt syntax.ATURI 14 OwnerDid string 15 IssueId int 16 - IssueAt string 17 Created time.Time 18 Title string 19 Body string ··· 42 Edited *time.Time 43 } 44 45 func NewIssue(tx *sql.Tx, issue *Issue) error { 46 defer tx.Rollback() 47 ··· 67 issue.IssueId = nextId 68 69 res, err := tx.Exec(` 70 - insert into issues (repo_at, owner_did, issue_id, title, body) 71 - values (?, ?, ?, ?, ?) 72 - `, issue.RepoAt, issue.OwnerDid, issue.IssueId, issue.Title, issue.Body) 73 if err != nil { 74 return err 75 } ··· 87 return nil 88 } 89 90 - func SetIssueAt(e Execer, repoAt syntax.ATURI, issueId int, issueAt string) error { 91 - _, err := e.Exec(`update issues set issue_at = ? where repo_at = ? and issue_id = ?`, issueAt, repoAt, issueId) 92 - return err 93 - } 94 - 95 func GetIssueAt(e Execer, repoAt syntax.ATURI, issueId int) (string, error) { 96 var issueAt string 97 err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt) ··· 117 select 118 i.id, 119 i.owner_did, 120 i.issue_id, 121 i.created, 122 i.title, ··· 136 select 137 id, 138 owner_did, 139 issue_id, 140 created, 141 title, ··· 156 var issue Issue 157 var createdAt string 158 var metadata IssueMetadata 159 - err := rows.Scan(&issue.ID, &issue.OwnerDid, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open, &metadata.CommentCount) 160 if err != nil { 161 return nil, err 162 } ··· 187 `select 188 i.id, 189 i.owner_did, 190 i.repo_at, 191 i.issue_id, 192 i.created, ··· 219 err := rows.Scan( 220 &issue.ID, 221 &issue.OwnerDid, 222 &issue.RepoAt, 223 &issue.IssueId, 224 &issueCreatedAt, ··· 262 } 263 264 func GetIssue(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, error) { 265 - query := `select id, owner_did, created, title, body, open from issues where repo_at = ? and issue_id = ?` 266 row := e.QueryRow(query, repoAt, issueId) 267 268 var issue Issue 269 var createdAt string 270 - err := row.Scan(&issue.ID, &issue.OwnerDid, &createdAt, &issue.Title, &issue.Body, &issue.Open) 271 if err != nil { 272 return nil, err 273 } ··· 282 } 283 284 func GetIssueWithComments(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, []Comment, error) { 285 - query := `select id, owner_did, issue_id, created, title, body, open, issue_at from issues where repo_at = ? and issue_id = ?` 286 row := e.QueryRow(query, repoAt, issueId) 287 288 var issue Issue 289 var createdAt string 290 - err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open, &issue.IssueAt) 291 if err != nil { 292 return nil, nil, err 293 }
··· 2 3 import ( 4 "database/sql" 5 + "fmt" 6 "time" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 + "tangled.sh/tangled.sh/core/api/tangled" 10 "tangled.sh/tangled.sh/core/appview/pagination" 11 ) 12 ··· 15 RepoAt syntax.ATURI 16 OwnerDid string 17 IssueId int 18 + Rkey string 19 Created time.Time 20 Title string 21 Body string ··· 44 Edited *time.Time 45 } 46 47 + func (i *Issue) AtUri() syntax.ATURI { 48 + return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", i.OwnerDid, tangled.RepoIssueNSID, i.Rkey)) 49 + } 50 + 51 func NewIssue(tx *sql.Tx, issue *Issue) error { 52 defer tx.Rollback() 53 ··· 73 issue.IssueId = nextId 74 75 res, err := tx.Exec(` 76 + insert into issues (repo_at, owner_did, rkey, issue_at, issue_id, title, body) 77 + values (?, ?, ?, ?, ?, ?, ?) 78 + `, issue.RepoAt, issue.OwnerDid, issue.Rkey, issue.AtUri(), issue.IssueId, issue.Title, issue.Body) 79 if err != nil { 80 return err 81 } ··· 93 return nil 94 } 95 96 func GetIssueAt(e Execer, repoAt syntax.ATURI, issueId int) (string, error) { 97 var issueAt string 98 err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt) ··· 118 select 119 i.id, 120 i.owner_did, 121 + i.rkey, 122 i.issue_id, 123 i.created, 124 i.title, ··· 138 select 139 id, 140 owner_did, 141 + rkey, 142 issue_id, 143 created, 144 title, ··· 159 var issue Issue 160 var createdAt string 161 var metadata IssueMetadata 162 + err := rows.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open, &metadata.CommentCount) 163 if err != nil { 164 return nil, err 165 } ··· 190 `select 191 i.id, 192 i.owner_did, 193 + i.rkey, 194 i.repo_at, 195 i.issue_id, 196 i.created, ··· 223 err := rows.Scan( 224 &issue.ID, 225 &issue.OwnerDid, 226 + &issue.Rkey, 227 &issue.RepoAt, 228 &issue.IssueId, 229 &issueCreatedAt, ··· 267 } 268 269 func GetIssue(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, error) { 270 + query := `select id, owner_did, rkey, created, title, body, open from issues where repo_at = ? and issue_id = ?` 271 row := e.QueryRow(query, repoAt, issueId) 272 273 var issue Issue 274 var createdAt string 275 + err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &createdAt, &issue.Title, &issue.Body, &issue.Open) 276 if err != nil { 277 return nil, err 278 } ··· 287 } 288 289 func GetIssueWithComments(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, []Comment, error) { 290 + query := `select id, owner_did, rkey, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?` 291 row := e.QueryRow(query, repoAt, issueId) 292 293 var issue Issue 294 var createdAt string 295 + err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open) 296 if err != nil { 297 return nil, nil, err 298 }
+7 -14
appview/issues/issues.go
··· 11 12 comatproto "github.com/bluesky-social/indigo/api/atproto" 13 "github.com/bluesky-social/indigo/atproto/data" 14 - "github.com/bluesky-social/indigo/atproto/syntax" 15 lexutil "github.com/bluesky-social/indigo/lex/util" 16 "github.com/go-chi/chi/v5" 17 ··· 80 return 81 } 82 83 - reactionCountMap, err := db.GetReactionCountMap(rp.db, syntax.ATURI(issue.IssueAt)) 84 if err != nil { 85 log.Println("failed to get issue reactions") 86 rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.") ··· 88 89 userReactions := map[db.ReactionKind]bool{} 90 if user != nil { 91 - userReactions = db.GetReactionStatusMap(rp.db, user.Did, syntax.ATURI(issue.IssueAt)) 92 } 93 94 issueOwnerIdent, err := rp.idResolver.ResolveIdent(r.Context(), issue.OwnerDid) ··· 99 rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 100 LoggedInUser: user, 101 RepoInfo: f.RepoInfo(user), 102 - Issue: *issue, 103 Comments: comments, 104 105 IssueOwnerHandle: issueOwnerIdent.Handle.String(), ··· 159 Rkey: tid.TID(), 160 Record: &lexutil.LexiconTypeDecoder{ 161 Val: &tangled.RepoIssueState{ 162 - Issue: issue.IssueAt, 163 State: closed, 164 }, 165 }, ··· 651 652 issue := &db.Issue{ 653 RepoAt: f.RepoAt, 654 Title: title, 655 Body: body, 656 OwnerDid: user.Did, ··· 669 return 670 } 671 atUri := f.RepoAt.String() 672 - resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{ 673 Collection: tangled.RepoIssueNSID, 674 Repo: user.Did, 675 - Rkey: tid.TID(), 676 Record: &lexutil.LexiconTypeDecoder{ 677 Val: &tangled.RepoIssue{ 678 Repo: atUri, ··· 689 return 690 } 691 692 - err = db.SetIssueAt(rp.db, f.RepoAt, issue.IssueId, resp.Uri) 693 - if err != nil { 694 - log.Println("failed to set issue at", err) 695 - rp.pages.Notice(w, "issues", "Failed to create issue.") 696 - return 697 - } 698 - 699 rp.notifier.NewIssue(r.Context(), issue) 700 701 rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId))
··· 11 12 comatproto "github.com/bluesky-social/indigo/api/atproto" 13 "github.com/bluesky-social/indigo/atproto/data" 14 lexutil "github.com/bluesky-social/indigo/lex/util" 15 "github.com/go-chi/chi/v5" 16 ··· 79 return 80 } 81 82 + reactionCountMap, err := db.GetReactionCountMap(rp.db, issue.AtUri()) 83 if err != nil { 84 log.Println("failed to get issue reactions") 85 rp.pages.Notice(w, "issues", "Failed to load issue. Try again later.") ··· 87 88 userReactions := map[db.ReactionKind]bool{} 89 if user != nil { 90 + userReactions = db.GetReactionStatusMap(rp.db, user.Did, issue.AtUri()) 91 } 92 93 issueOwnerIdent, err := rp.idResolver.ResolveIdent(r.Context(), issue.OwnerDid) ··· 98 rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 99 LoggedInUser: user, 100 RepoInfo: f.RepoInfo(user), 101 + Issue: issue, 102 Comments: comments, 103 104 IssueOwnerHandle: issueOwnerIdent.Handle.String(), ··· 158 Rkey: tid.TID(), 159 Record: &lexutil.LexiconTypeDecoder{ 160 Val: &tangled.RepoIssueState{ 161 + Issue: issue.AtUri().String(), 162 State: closed, 163 }, 164 }, ··· 650 651 issue := &db.Issue{ 652 RepoAt: f.RepoAt, 653 + Rkey: tid.TID(), 654 Title: title, 655 Body: body, 656 OwnerDid: user.Did, ··· 669 return 670 } 671 atUri := f.RepoAt.String() 672 + _, err = client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{ 673 Collection: tangled.RepoIssueNSID, 674 Repo: user.Did, 675 + Rkey: issue.Rkey, 676 Record: &lexutil.LexiconTypeDecoder{ 677 Val: &tangled.RepoIssue{ 678 Repo: atUri, ··· 689 return 690 } 691 692 rp.notifier.NewIssue(r.Context(), issue) 693 694 rp.pages.HxLocation(w, fmt.Sprintf("/%s/issues/%d", f.OwnerSlashRepo(), issue.IssueId))
+1 -1
appview/pages/pages.go
··· 793 LoggedInUser *oauth.User 794 RepoInfo repoinfo.RepoInfo 795 Active string 796 - Issue db.Issue 797 Comments []db.Comment 798 IssueOwnerHandle string 799
··· 793 LoggedInUser *oauth.User 794 RepoInfo repoinfo.RepoInfo 795 Active string 796 + Issue *db.Issue 797 Comments []db.Comment 798 IssueOwnerHandle string 799
+1 -1
appview/pages/templates/repo/issues/issue.html
··· 54 "Kind" $kind 55 "Count" (index $.Reactions $kind) 56 "IsReacted" (index $.UserReacted $kind) 57 - "ThreadAt" $.Issue.IssueAt) 58 }} 59 {{ end }} 60 </div>
··· 54 "Kind" $kind 55 "Count" (index $.Reactions $kind) 56 "IsReacted" (index $.UserReacted $kind) 57 + "ThreadAt" $.Issue.AtUri) 58 }} 59 {{ end }} 60 </div>