Monorepo for Tangled tangled.org
856
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview: be more compatible with legacy comment records #354

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

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:xasnlahkri4ewmbuzly2rlc5/sh.tangled.repo.pull/3mlehfetyr322
+118 -42
Diff #1
-5
appview/db/comments.go
··· 11 11 12 12 "github.com/bluesky-social/indigo/api/atproto" 13 13 "github.com/bluesky-social/indigo/atproto/syntax" 14 - "tangled.org/core/api/tangled" 15 14 "tangled.org/core/appview/models" 16 15 "tangled.org/core/orm" 17 16 ) 18 17 19 18 func PutComment(tx *sql.Tx, c *models.Comment, references []syntax.ATURI) error { 20 - if c.Collection == "" { 21 - c.Collection = tangled.FeedCommentNSID 22 - } 23 - 24 19 var bodyBlobs, replyToUri, replyToCid *string 25 20 if len(c.Body.Blobs) > 0 { 26 21 encoded, err := json.Marshal(c.Body.Blobs)
+58 -17
appview/migration/migrate_use_feed_comment.go
··· 1 1 package migration 2 2 3 3 import ( 4 + "bytes" 4 5 "context" 5 6 "fmt" 6 7 ··· 10 11 "github.com/bluesky-social/indigo/atproto/syntax" 11 12 "github.com/bluesky-social/indigo/lex/util" 12 13 "github.com/bluesky-social/indigo/xrpc" 14 + "github.com/ipfs/go-cid" 15 + "github.com/multiformats/go-multihash" 13 16 "tangled.org/core/api/tangled" 14 17 "tangled.org/core/appview/db" 18 + "tangled.org/core/appview/models" 15 19 "tangled.org/core/orm" 16 20 ) 17 21 ··· 26 30 return fmt.Errorf("unexpected collection: '%s'", record.Collection()) 27 31 } 28 32 29 - comment, err := db.GetComment(s.db, orm.FilterEq("at_uri", record)) 33 + comments, err := db.GetComments(s.db, orm.FilterEq("at_uri", record)) 30 34 if err != nil { 31 35 return fmt.Errorf("db: %w", err) 32 36 } 37 + if len(comments) < 1 { 38 + l.Info("can't found legacy record from db. skipping migration") 39 + return nil 40 + } 41 + comment := comments[0] 33 42 34 43 comment.Collection = tangled.FeedCommentNSID 35 44 ··· 58 67 // fail if it isn't ready 59 68 uri = syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", uri.Authority(), tangled.FeedCommentNSID, uri.RecordKey())) 60 69 61 - cid, err := s.getRecordCid(ctx, uri) 70 + cid, err := s.guessParentCommentCid(uri, &comment) 62 71 if err != nil { 63 - return fmt.Errorf("pds: getRecordCid for replyTo.uri: %w", err) 72 + return fmt.Errorf("cbor: guessParentCommentCid for replyTo.uri: %w", err) 64 73 } 65 74 comment.ReplyTo.Uri = uri.String() 66 75 comment.ReplyTo.Cid = cid.String() ··· 69 78 // use same rkey for new record 70 79 rkey := record.RecordKey().String() 71 80 72 - if _, err := comatproto.RepoApplyWrites(ctx, client, &comatproto.RepoApplyWrites_Input{ 73 - Repo: did.String(), 74 - Writes: []*comatproto.RepoApplyWrites_Input_Writes_Elem{ 75 - {RepoApplyWrites_Delete: &comatproto.RepoApplyWrites_Delete{ 76 - Collection: record.Collection().String(), 77 - Rkey: rkey, 78 - }}, 79 - {RepoApplyWrites_Create: &comatproto.RepoApplyWrites_Create{ 80 - Collection: tangled.FeedCommentNSID, 81 - Rkey: &rkey, 82 - Value: &util.LexiconTypeDecoder{Val: comment.AsRecord()}, 83 - }}, 84 - }, 81 + if _, err := comatproto.RepoDeleteRecord(ctx, client, &comatproto.RepoDeleteRecord_Input{ 82 + Repo: did.String(), 83 + Collection: record.Collection().String(), 84 + Rkey: rkey, 85 85 }); err != nil { 86 - return fmt.Errorf("pds: applyWrites: %w", err) 86 + l.Info("Failed to cleanup old record. Proceeding migration...", "err", err) 87 + } 88 + 89 + // ensure new record is missing in PDS 90 + if _, err := agnostic.RepoGetRecord(ctx, client, "", tangled.FeedCommentNSID, did.String(), rkey); err == nil { 91 + l.Info("New comment record already exists") 92 + } else { 93 + // insert new record 94 + if _, err := comatproto.RepoCreateRecord(ctx, client, &comatproto.RepoCreateRecord_Input{ 95 + Repo: did.String(), 96 + Collection: tangled.FeedCommentNSID, 97 + Rkey: &rkey, 98 + Record: &util.LexiconTypeDecoder{Val: comment.AsRecord()}, 99 + }); err != nil { 100 + return fmt.Errorf("pds: putRecord: %w", err) 101 + } 87 102 } 88 103 89 104 return nil ··· 111 126 112 127 return cid, nil 113 128 } 129 + 130 + func (s *Migration) guessParentCommentCid(uri syntax.ATURI, comment *models.Comment) (syntax.CID, error) { 131 + parent, err := db.GetComment(s.db, orm.FilterEq("did", uri.Authority()), orm.FilterEq("rkey", uri.RecordKey())) 132 + if err != nil { 133 + return "", fmt.Errorf("db: failed to queyr subject comment: %w", err) 134 + } 135 + if parent.Deleted != nil { 136 + // leave cid empty. reply comment won't pass the schema validation. 137 + return "", nil 138 + } 139 + 140 + // since parent comment is also migrating, parent comments subject.cid might be empty 141 + if parent.Subject.Cid == "" { 142 + parent.Subject.Cid = comment.Subject.Cid 143 + } 144 + 145 + buf := new(bytes.Buffer) 146 + if err := parent.AsRecord().MarshalCBOR(buf); err != nil { 147 + return "", fmt.Errorf("MarshalCBOR: %w", err) 148 + } 149 + c, err := cid.NewPrefixV1(cid.DagCBOR, multihash.SHA2_256).Sum(buf.Bytes()) 150 + if err != nil { 151 + return "", fmt.Errorf("cid: sum: %w", err) 152 + } 153 + return syntax.CID(c.String()), nil 154 + }
+12 -5
appview/models/comment.go
··· 44 44 } 45 45 46 46 func (c Comment) AsRecord() typegen.CBORMarshaler { 47 - // can't convert to record for legacy types 48 - if c.Collection != tangled.FeedCommentNSID { 49 - return nil 50 - } 51 47 var pullRoundIdx *int64 52 48 if c.PullRoundIdx != nil { 53 49 pullRoundIdx = new(int64) ··· 204 200 if r.ReplyTo == nil { 205 201 continue 206 202 } 207 - if parent, exists := toplevel[syntax.ATURI(r.ReplyTo.Uri)]; exists { 203 + uri := syntax.ATURI(r.ReplyTo.Uri) 204 + if parent, exists := toplevel[uri]; exists { 205 + parent.Replies = append(parent.Replies, r) 206 + continue 207 + } 208 + // HACK: fallback to legacy comment collections 209 + if parent, exists := toplevel[syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", uri.Authority(), tangled.RepoIssueCommentNSID, uri.RecordKey()))]; exists { 208 210 parent.Replies = append(parent.Replies, r) 211 + continue 212 + } 213 + if parent, exists := toplevel[syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", uri.Authority(), tangled.RepoPullCommentNSID, uri.RecordKey()))]; exists { 214 + parent.Replies = append(parent.Replies, r) 215 + continue 209 216 } 210 217 } 211 218
+1 -7
appview/pages/templates/fragments/comment/commentList.html
··· 38 38 <input name="subject-cid" type="hidden" value="{{ $item.Self.Subject.Cid }}"> 39 39 <input name="reply-to-uri" type="hidden" value="{{ $item.Self.AtUri }}"> 40 40 <input name="reply-to-cid" type="hidden" value="{{ $item.Self.Cid }}"> 41 - {{ if $item.Self.IsLegacy }} 42 - <div class="py-2 px-6 border-t flex gap-2 items-center border-gray-300 dark:border-gray-700"> 43 - <span class="text-orange-500">Can't reply to legacy comment.</span> 44 - </div> 45 - {{ else }} 46 - {{ template "fragments/comment/replyPlaceholder" (dict "LoggedInUser" $root.LoggedInUser) }} 47 - {{ end }} 41 + {{ template "fragments/comment/replyPlaceholder" (dict "LoggedInUser" $root.LoggedInUser) }} 48 42 </div> 49 43 </div> 50 44 {{ end }}
+47 -8
appview/state/comment.go
··· 1 1 package state 2 2 3 3 import ( 4 + "bytes" 4 5 "fmt" 5 6 "net/http" 6 7 "strconv" ··· 10 11 "github.com/bluesky-social/indigo/atproto/syntax" 11 12 lexutil "github.com/bluesky-social/indigo/lex/util" 12 13 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 14 + "github.com/ipfs/go-cid" 15 + "github.com/multiformats/go-multihash" 13 16 14 17 "tangled.org/core/api/tangled" 15 18 "tangled.org/core/appview/db" ··· 176 179 var replyTo *comatproto.RepoStrongRef 177 180 replyToUriRaw := r.FormValue("reply-to-uri") 178 181 replyToCidRaw := r.FormValue("reply-to-cid") 179 - if replyToUriRaw != "" && replyToCidRaw != "" { 180 - uri, err := syntax.ParseATURI(replyToUriRaw) 182 + if replyToUriRaw != "" { 183 + replyToUri, err := syntax.ParseATURI(replyToUriRaw) 181 184 if err != nil { 182 185 s.pages.Notice(w, noticeId, "reply-to-uri should be valid AT-URI") 183 186 return 184 187 } 185 - cid, err := syntax.ParseCID(replyToCidRaw) 186 - if err != nil { 187 - s.pages.Notice(w, noticeId, "reply-to-cid should be valid CID") 188 - return 188 + // force replyTo.uri to `sh.tangled.feed.comment` collection, even when they aren't. 189 + // we are expecting parent comment will be migrated later. 190 + replyToUri = syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", replyToUri.Authority(), tangled.FeedCommentNSID, replyToUri.RecordKey())) 191 + 192 + var replyToCid syntax.CID 193 + if replyToCidRaw != "" { 194 + replyToCid, err = syntax.ParseCID(replyToCidRaw) 195 + if err != nil { 196 + s.pages.Notice(w, noticeId, "reply-to-cid should be valid CID") 197 + return 198 + } 199 + } else { 200 + // guess parent comment cid 201 + subjectComment, err := db.GetComment(s.db, orm.FilterEq("did", replyToUri.Authority()), orm.FilterEq("rkey", replyToUri.RecordKey())) 202 + if err != nil { 203 + l.Warn("db: failed to query subject comment", "err", err) 204 + s.pages.Notice(w, noticeId, "Subject record is unknown.") 205 + return 206 + } 207 + if subjectComment.Deleted != nil { 208 + // leave cid empty. reply comment won't pass the schema validation. 209 + } else { 210 + // guess cid from content 211 + c, err := func() (cid.Cid, error) { 212 + buf := new(bytes.Buffer) 213 + if subjectComment.Subject.Cid == "" { 214 + subjectComment.Subject.Cid = subject.Cid 215 + } 216 + if err := subjectComment.AsRecord().MarshalCBOR(buf); err != nil { 217 + return cid.Undef, fmt.Errorf("MarshalCBOR: %w", err) 218 + } 219 + return cid.NewPrefixV1(cid.DagCBOR, multihash.SHA2_256).Sum(buf.Bytes()) 220 + }() 221 + if err != nil { 222 + l.Warn("cbor: failed to guess parent comment cid", "err", err) 223 + s.pages.Notice(w, noticeId, "Parent comment is invalid.") 224 + return 225 + } 226 + replyToCid = syntax.CID(c.String()) 227 + } 189 228 } 190 229 replyTo = &comatproto.RepoStrongRef{ 191 - Uri: uri.String(), 192 - Cid: cid.String(), 230 + Uri: replyToUri.String(), 231 + Cid: replyToCid.String(), 193 232 } 194 233 } 195 234

History

2 rounds 0 comments
sign up or login to add to the discussion
1 commit
expand
appview: be more compatible with legacy comment records
merge conflicts detected
expand
  • appview/migration/migration.go:71
expand 0 comments
1 commit
expand
appview: be more compatible with legacy comment records
expand 0 comments