Monorepo for Tangled tangled.org

appview: replace PullComment to Comment #865

open opened by boltless.me targeting master from sl/wnrvrwyvrlzo
Labels

None yet.

assignee

None yet.

Participants 2
AT URI
at://did:plc:xasnlahkri4ewmbuzly2rlc5/sh.tangled.repo.pull/3m7iohv2yb422
+126 -28
Interdiff #4 #5
+14 -10
appview/db/comments.go
··· 10 "time" 11 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 "tangled.org/core/appview/models" 14 "tangled.org/core/orm" 15 ) 16 17 func PutComment(tx *sql.Tx, c *models.Comment) error { 18 result, err := tx.Exec( 19 `insert into comments ( 20 did, 21 rkey, 22 subject_at, 23 reply_to, ··· 25 pull_submission_id, 26 created 27 ) 28 - values (?, ?, ?, ?, ?, ?, ?) 29 - on conflict(did, rkey) do update set 30 subject_at = excluded.subject_at, 31 reply_to = excluded.reply_to, 32 body = excluded.body, ··· 39 else comments.edited 40 end`, 41 c.Did, 42 c.Rkey, 43 c.Subject, 44 c.ReplyTo, ··· 101 select 102 id, 103 did, 104 rkey, 105 subject_at, 106 reply_to, ··· 122 for rows.Next() { 123 var comment models.Comment 124 var created string 125 - var rkey, edited, deleted, replyTo sql.Null[string] 126 err := rows.Scan( 127 &comment.Id, 128 &comment.Did, 129 - &rkey, 130 &comment.Subject, 131 &replyTo, 132 &comment.Body, ··· 139 return nil, err 140 } 141 142 - // this is a remnant from old times, newer comments always have rkey 143 - if rkey.Valid { 144 - comment.Rkey = rkey.V 145 - } 146 - 147 if t, err := time.Parse(time.RFC3339, created); err == nil { 148 comment.Created = t 149 } ··· 172 if err := rows.Err(); err != nil { 173 return nil, err 174 } 175 176 // collect references from each comments 177 commentAts := slices.Collect(maps.Keys(commentMap)) ··· 191 } 192 193 sort.Slice(comments, func(i, j int) bool { 194 - return comments[i].Created.After(comments[j].Created) 195 }) 196 197 return comments, nil
··· 10 "time" 11 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 + "tangled.org/core/api/tangled" 14 "tangled.org/core/appview/models" 15 "tangled.org/core/orm" 16 ) 17 18 func PutComment(tx *sql.Tx, c *models.Comment) error { 19 + if c.Collection == "" { 20 + c.Collection = tangled.CommentNSID 21 + } 22 result, err := tx.Exec( 23 `insert into comments ( 24 did, 25 + collection, 26 rkey, 27 subject_at, 28 reply_to, ··· 30 pull_submission_id, 31 created 32 ) 33 + values (?, ?, ?, ?, ?, ?, ?, ?) 34 + on conflict(did, collection, rkey) do update set 35 subject_at = excluded.subject_at, 36 reply_to = excluded.reply_to, 37 body = excluded.body, ··· 44 else comments.edited 45 end`, 46 c.Did, 47 + c.Collection, 48 c.Rkey, 49 c.Subject, 50 c.ReplyTo, ··· 107 select 108 id, 109 did, 110 + collection, 111 rkey, 112 subject_at, 113 reply_to, ··· 129 for rows.Next() { 130 var comment models.Comment 131 var created string 132 + var edited, deleted, replyTo sql.Null[string] 133 err := rows.Scan( 134 &comment.Id, 135 &comment.Did, 136 + &comment.Collection, 137 + &comment.Rkey, 138 &comment.Subject, 139 &replyTo, 140 &comment.Body, ··· 147 return nil, err 148 } 149 150 if t, err := time.Parse(time.RFC3339, created); err == nil { 151 comment.Created = t 152 } ··· 175 if err := rows.Err(); err != nil { 176 return nil, err 177 } 178 + defer rows.Close() 179 180 // collect references from each comments 181 commentAts := slices.Collect(maps.Keys(commentMap)) ··· 195 } 196 197 sort.Slice(comments, func(i, j int) bool { 198 + return comments[i].Created.Before(comments[j].Created) 199 }) 200 201 return comments, nil
+1 -1
appview/db/db.go
··· 1198 deleted text, 1199 1200 -- constraints 1201 - unique(did, rkey) 1202 ); 1203 1204 insert into comments (
··· 1198 deleted text, 1199 1200 -- constraints 1201 + unique(did, collection, rkey) 1202 ); 1203 1204 insert into comments (
appview/db/pulls.go

This file has not been changed.

appview/db/reference.go

This file has not been changed.

+35 -14
appview/models/comment.go
··· 6 "time" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 "tangled.org/core/api/tangled" 10 ) 11 12 type Comment struct { 13 Id int64 14 Did syntax.DID 15 Rkey string 16 Subject syntax.ATURI 17 ReplyTo *syntax.ATURI ··· 25 } 26 27 func (c *Comment) AtUri() syntax.ATURI { 28 - return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", c.Did, tangled.CommentNSID, c.Rkey)) 29 } 30 31 - func (c *Comment) AsRecord() tangled.Comment { 32 mentions := make([]string, len(c.Mentions)) 33 for i, did := range c.Mentions { 34 mentions[i] = string(did) ··· 42 replyToStr := c.ReplyTo.String() 43 replyTo = &replyToStr 44 } 45 - return tangled.Comment{ 46 - Subject: c.Subject.String(), 47 - Body: c.Body, 48 - CreatedAt: c.Created.Format(time.RFC3339), 49 - ReplyTo: replyTo, 50 - Mentions: mentions, 51 - References: references, 52 } 53 } 54 ··· 75 return nil 76 } 77 78 - func CommentFromRecord(did, rkey string, record tangled.Comment) (*Comment, error) { 79 created, err := time.Parse(time.RFC3339, record.CreatedAt) 80 if err != nil { 81 created = time.Now() 82 } 83 84 - ownerDid := did 85 - 86 if _, err = syntax.ParseATURI(record.Subject); err != nil { 87 return nil, err 88 } ··· 103 } 104 105 comment := Comment{ 106 - Did: syntax.DID(ownerDid), 107 - Rkey: rkey, 108 Body: record.Body, 109 Subject: syntax.ATURI(record.Subject), 110 ReplyTo: replyTo,
··· 6 "time" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 + "github.com/whyrusleeping/cbor-gen" 10 "tangled.org/core/api/tangled" 11 ) 12 13 type Comment struct { 14 Id int64 15 Did syntax.DID 16 + Collection syntax.NSID 17 Rkey string 18 Subject syntax.ATURI 19 ReplyTo *syntax.ATURI ··· 27 } 28 29 func (c *Comment) AtUri() syntax.ATURI { 30 + return syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", c.Did, c.Collection, c.Rkey)) 31 } 32 33 + func (c *Comment) AsRecord() typegen.CBORMarshaler { 34 mentions := make([]string, len(c.Mentions)) 35 for i, did := range c.Mentions { 36 mentions[i] = string(did) ··· 44 replyToStr := c.ReplyTo.String() 45 replyTo = &replyToStr 46 } 47 + switch c.Collection { 48 + case tangled.RepoIssueCommentNSID: 49 + return &tangled.RepoIssueComment{ 50 + Issue: c.Subject.String(), 51 + Body: c.Body, 52 + CreatedAt: c.Created.Format(time.RFC3339), 53 + ReplyTo: replyTo, 54 + Mentions: mentions, 55 + References: references, 56 + } 57 + case tangled.RepoPullCommentNSID: 58 + return &tangled.RepoPullComment{ 59 + Pull: c.Subject.String(), 60 + Body: c.Body, 61 + CreatedAt: c.Created.Format(time.RFC3339), 62 + Mentions: mentions, 63 + References: references, 64 + } 65 + default: // default to CommentNSID 66 + return &tangled.Comment{ 67 + Subject: c.Subject.String(), 68 + Body: c.Body, 69 + CreatedAt: c.Created.Format(time.RFC3339), 70 + ReplyTo: replyTo, 71 + Mentions: mentions, 72 + References: references, 73 + } 74 } 75 } 76 ··· 97 return nil 98 } 99 100 + func CommentFromRecord(did syntax.DID, rkey syntax.RecordKey, record tangled.Comment) (*Comment, error) { 101 created, err := time.Parse(time.RFC3339, record.CreatedAt) 102 if err != nil { 103 created = time.Now() 104 } 105 106 if _, err = syntax.ParseATURI(record.Subject); err != nil { 107 return nil, err 108 } ··· 123 } 124 125 comment := Comment{ 126 + Did: did, 127 + Collection: tangled.CommentNSID, 128 + Rkey: rkey.String(), 129 Body: record.Body, 130 Subject: syntax.ATURI(record.Subject), 131 ReplyTo: replyTo,
appview/models/pull.go

This file has not been changed.

appview/notify/db/db.go

This file has not been changed.

appview/notify/merged_notifier.go

This file has not been changed.

appview/notify/notifier.go

This file has not been changed.

appview/notify/posthog/notifier.go

This file has not been changed.

appview/pages/templates/repo/pulls/pull.html

This file has not been changed.

appview/pulls/opengraph.go

This file has not been changed.

+4 -3
appview/pulls/pulls.go
··· 724 725 comment := models.Comment{ 726 Did: syntax.DID(user.Active.Did), 727 Rkey: tid.TID(), 728 Subject: pull.AtUri(), 729 ReplyTo: nil, ··· 738 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 739 return 740 } 741 - record := comment.AsRecord() 742 743 client, err := s.oauth.AuthorizedClient(r) 744 if err != nil { ··· 746 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 747 return 748 } 749 _, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 750 - Collection: tangled.CommentNSID, 751 Repo: comment.Did.String(), 752 Rkey: comment.Rkey, 753 Record: &lexutil.LexiconTypeDecoder{ 754 - Val: &record, 755 }, 756 }) 757 if err != nil {
··· 724 725 comment := models.Comment{ 726 Did: syntax.DID(user.Active.Did), 727 + Collection: tangled.CommentNSID, 728 Rkey: tid.TID(), 729 Subject: pull.AtUri(), 730 ReplyTo: nil, ··· 739 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 740 return 741 } 742 743 client, err := s.oauth.AuthorizedClient(r) 744 if err != nil { ··· 746 s.pages.Notice(w, "pull-comment", "Failed to create comment.") 747 return 748 } 749 + 750 _, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 751 + Collection: comment.Collection.String(), 752 Repo: comment.Did.String(), 753 Rkey: comment.Rkey, 754 Record: &lexutil.LexiconTypeDecoder{ 755 + Val: comment.AsRecord(), 756 }, 757 }) 758 if err != nil {
+71
appview/ingester.go
··· 79 err = i.ingestString(e) 80 case tangled.RepoIssueNSID: 81 err = i.ingestIssue(ctx, e) 82 case tangled.RepoIssueCommentNSID: 83 err = i.ingestIssueComment(e) 84 case tangled.LabelDefinitionNSID: ··· 928 return nil 929 } 930 931 func (i *Ingester) ingestLabelDefinition(e *jmodels.Event) error { 932 did := e.Did 933 rkey := e.Commit.RKey
··· 79 err = i.ingestString(e) 80 case tangled.RepoIssueNSID: 81 err = i.ingestIssue(ctx, e) 82 + case tangled.CommentNSID: 83 + err = i.ingestComment(e) 84 case tangled.RepoIssueCommentNSID: 85 err = i.ingestIssueComment(e) 86 case tangled.LabelDefinitionNSID: ··· 930 return nil 931 } 932 933 + func (i *Ingester) ingestComment(e *jmodels.Event) error { 934 + did := e.Did 935 + rkey := e.Commit.RKey 936 + 937 + var err error 938 + 939 + l := i.Logger.With("handler", "ingestComment", "nsid", e.Commit.Collection, "did", did, "rkey", rkey) 940 + l.Info("ingesting record") 941 + 942 + ddb, ok := i.Db.Execer.(*db.DB) 943 + if !ok { 944 + return fmt.Errorf("failed to index issue comment record, invalid db cast") 945 + } 946 + 947 + switch e.Commit.Operation { 948 + case jmodels.CommitOperationCreate, jmodels.CommitOperationUpdate: 949 + raw := json.RawMessage(e.Commit.Record) 950 + record := tangled.Comment{} 951 + err = json.Unmarshal(raw, &record) 952 + if err != nil { 953 + return fmt.Errorf("invalid record: %w", err) 954 + } 955 + 956 + comment, err := models.CommentFromRecord(syntax.DID(did), syntax.RecordKey(rkey), record) 957 + if err != nil { 958 + return fmt.Errorf("failed to parse comment from record: %w", err) 959 + } 960 + 961 + // TODO: ingest pull comments 962 + // we aren't ingesting pull comments yet because pull itself isn't fully atprotated. 963 + // so we cannot know which round this comment is pointing to 964 + if comment.Subject.Collection().String() == tangled.RepoPullNSID { 965 + l.Info("skip ingesting pull comments") 966 + return nil 967 + } 968 + 969 + if err := comment.Validate(); err != nil { 970 + return fmt.Errorf("failed to validate comment: %w", err) 971 + } 972 + 973 + tx, err := ddb.Begin() 974 + if err != nil { 975 + return fmt.Errorf("failed to start transaction: %w", err) 976 + } 977 + defer tx.Rollback() 978 + 979 + err = db.PutComment(tx, comment) 980 + if err != nil { 981 + return fmt.Errorf("failed to create comment: %w", err) 982 + } 983 + 984 + return tx.Commit() 985 + 986 + case jmodels.CommitOperationDelete: 987 + if err := db.DeleteComments( 988 + ddb, 989 + orm.FilterEq("did", did), 990 + orm.FilterEq("collection", e.Commit.Collection), 991 + orm.FilterEq("rkey", rkey), 992 + ); err != nil { 993 + return fmt.Errorf("failed to delete comment record: %w", err) 994 + } 995 + 996 + return nil 997 + } 998 + 999 + return nil 1000 + } 1001 + 1002 func (i *Ingester) ingestLabelDefinition(e *jmodels.Event) error { 1003 did := e.Did 1004 rkey := e.Commit.RKey
+1
appview/state/state.go
··· 118 tangled.StringNSID, 119 tangled.RepoIssueNSID, 120 tangled.RepoIssueCommentNSID, 121 tangled.LabelDefinitionNSID, 122 tangled.LabelOpNSID, 123 },
··· 118 tangled.StringNSID, 119 tangled.RepoIssueNSID, 120 tangled.RepoIssueCommentNSID, 121 + tangled.CommentNSID, 122 tangled.LabelDefinitionNSID, 123 tangled.LabelOpNSID, 124 },

History

8 rounds 4 comments
sign up or login to add to the discussion
1 commit
expand
appview: replace PullComment to Comment
2/3 timeout, 1/3 success
expand
merge conflicts detected
expand
  • appview/notify/db/db.go:260
  • appview/notify/merged_notifier.go:81
  • appview/notify/notifier.go:22
  • appview/pulls/opengraph.go:277
expand 0 comments
1 commit
expand
appview: replace PullComment to Comment
2/3 failed, 1/3 success
expand
expand 0 comments
1 commit
expand
appview: replace PullComment to Comment
3/3 success
expand
expand 0 comments
1 commit
expand
appview: replace PullComment to Comment
3/3 success
expand
expand 1 comment

here, the sort order is reversed, it should be .Before.

1 commit
expand
appview: replace PullComment to Comment
1/3 failed, 2/3 success
expand
expand 0 comments
1 commit
expand
appview: replace PullComment to Comment
1/3 failed, 2/3 success
expand
expand 0 comments
1 commit
expand
appview: replace PullComment to Comment
3/3 success
expand
expand 3 comments

here will this delete all comments made on tangled thus far? don't think this is the right approach if so.

I should've been more precise about my expression. Existing comments won't be dropped as they are stored in issue_comments and pull_comments table (I'm just dropping legacy table with same name there), but yeah this PR itself doesn't include the backward compatibility layer yet so old comments won't be rendered.

Honestly this PR hasn't been updated since you two suggested to just ingest old records. I'll push more commits on top of this stack.

As a side note: I'd suggest to not publish the new sh.tangled.comment lexicon yet.

This unified comment record can be used for PR review comments and it might make us to modify the schema again. I think it would be safest to publish this when PR redesign discussion is finished.

1 commit
expand
appview: replace PullComment to Comment
3/3 success
expand
expand 0 comments