Monorepo for Tangled tangled.org

appview,lexicons: atprotate the mentions & references #761

merged opened by boltless.me targeting master from feat/mentions

Storing references parsed from the markdown body in atproto record and DB. There can be lots of reference types considering the from/to types so storing both as AT-URIs

Using sql.Tx more to combine multiple DB query to single recoverable operation.

Note: Pulls don't have mentinos/references yet

Signed-off-by: Seongmin Lee git@boltless.me

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:xasnlahkri4ewmbuzly2rlc5/sh.tangled.repo.pull/3m4vklvknse22
+58 -39
Interdiff #0 #1
api/tangled/cbor_gen.go

This patch was likely rebased, as context lines do not match.

api/tangled/issuecomment.go

This file has not been changed.

api/tangled/pullcomment.go

This file has not been changed.

api/tangled/repoissue.go

This file has not been changed.

+4 -4
appview/db/db.go
··· 561 561 email_notifications integer not null default 0 562 562 ); 563 563 564 - create table if not exists references ( 564 + create table if not exists reference_links ( 565 565 id integer primary key autoincrement, 566 566 from_at text not null, 567 567 to_at text not null, 568 - unique (from, to) 568 + unique (from_at, to_at) 569 569 ); 570 570 571 571 create table if not exists migrations ( ··· 578 578 create index if not exists idx_notifications_recipient_read on notifications(recipient_did, read); 579 579 create index if not exists idx_stars_created on stars(created); 580 580 create index if not exists idx_stars_repo_at_created on stars(repo_at, created); 581 - create index if not exists idx_references_from_at on references(from_at); 582 - create index if not exists idx_references_to_at on references(to_at); 581 + create index if not exists idx_references_from_at on reference_links(from_at); 582 + create index if not exists idx_references_to_at on reference_links(to_at); 583 583 `) 584 584 if err != nil { 585 585 return nil, err
+9 -9
appview/db/issues.go
··· 76 76 } 77 77 78 78 if err := putReferences(tx, issue.AtUri(), issue.References); err != nil { 79 - return fmt.Errorf("put references: %w", err) 79 + return fmt.Errorf("put reference_links: %w", err) 80 80 } 81 81 return nil 82 82 } ··· 93 93 } 94 94 95 95 if err := putReferences(tx, issue.AtUri(), issue.References); err != nil { 96 - return fmt.Errorf("put references: %w", err) 96 + return fmt.Errorf("put reference_links: %w", err) 97 97 } 98 98 return nil 99 99 } ··· 253 253 // collect references for each issue 254 254 allReferencs, err := GetReferencesAll(e, FilterIn("from_at", issueAts)) 255 255 if err != nil { 256 - return nil, fmt.Errorf("failed to query references: %w", err) 256 + return nil, fmt.Errorf("failed to query reference_links: %w", err) 257 257 } 258 258 for issueAt, references := range allReferencs { 259 259 if issue, ok := issueMap[issueAt.String()]; ok { ··· 385 385 return 0, err 386 386 } 387 387 388 - if err := putReferences(tx, c.AtUri(), c.References); err != nil { 389 - return 0, fmt.Errorf("put references: %w", err) 390 - } 391 - 392 388 id, err := result.LastInsertId() 393 389 if err != nil { 394 390 return 0, err 395 391 } 396 392 393 + if err := putReferences(tx, c.AtUri(), c.References); err != nil { 394 + return 0, fmt.Errorf("put reference_links: %w", err) 395 + } 396 + 397 397 return id, nil 398 398 } 399 399 ··· 508 508 commentAts := slices.Collect(maps.Keys(commentMap)) 509 509 allReferencs, err := GetReferencesAll(e, FilterIn("from_at", commentAts)) 510 510 if err != nil { 511 - return nil, fmt.Errorf("failed to query references: %w", err) 511 + return nil, fmt.Errorf("failed to query reference_links: %w", err) 512 512 } 513 513 for commentAt, references := range allReferencs { 514 514 if comment, ok := commentMap[commentAt.String()]; ok { ··· 542 542 uri := syntax.ATURI(fmt.Sprintf("at://%s/%s/%s", did, tangled.RepoIssueNSID, rkey)) 543 543 err = deleteReferences(tx, uri) 544 544 if err != nil { 545 - return fmt.Errorf("delete references: %w", err) 545 + return fmt.Errorf("delete reference_links: %w", err) 546 546 } 547 547 548 548 return nil
+4 -4
appview/db/pulls.go
··· 432 432 submissionIds := slices.Collect(maps.Keys(submissionMap)) 433 433 comments, err := GetPullComments(e, FilterIn("submission_id", submissionIds)) 434 434 if err != nil { 435 - return nil, err 435 + return nil, fmt.Errorf("failed to get pull comments: %w", err) 436 436 } 437 437 for _, comment := range comments { 438 438 if submission, ok := submissionMap[comment.SubmissionId]; ok { ··· 526 526 commentAts := slices.Collect(maps.Keys(commentMap)) 527 527 allReferencs, err := GetReferencesAll(e, FilterIn("from_at", commentAts)) 528 528 if err != nil { 529 - return nil, fmt.Errorf("failed to query references: %w", err) 529 + return nil, fmt.Errorf("failed to query reference_links: %w", err) 530 530 } 531 531 for commentAt, references := range allReferencs { 532 532 if comment, ok := commentMap[commentAt.String()]; ok { ··· 540 540 } 541 541 542 542 sort.Slice(comments, func(i, j int) bool { 543 - return comments[i].Created.After(comments[j].Created) 543 + return comments[i].Created.Before(comments[j].Created) 544 544 }) 545 545 546 546 return comments, nil ··· 643 643 } 644 644 645 645 if err := putReferences(tx, comment.AtUri(), comment.References); err != nil { 646 - return 0, fmt.Errorf("put references: %w", err) 646 + return 0, fmt.Errorf("put reference_links: %w", err) 647 647 } 648 648 649 649 return i, nil
+21 -20
appview/db/reference.go
··· 10 10 "tangled.org/core/appview/models" 11 11 ) 12 12 13 - // FindReferences resolves refLinks to Issue/PR/IssueComment/PullComment ATURIs. 13 + // ValidateReferenceLinks resolves refLinks to Issue/PR/IssueComment/PullComment ATURIs. 14 14 // It will ignore missing refLinks. 15 - func FindReferences(e Execer, refLinks []models.ReferenceLink) ([]syntax.ATURI, error) { 15 + func ValidateReferenceLinks(e Execer, refLinks []models.ReferenceLink) ([]syntax.ATURI, error) { 16 16 var ( 17 17 issueRefs []models.ReferenceLink 18 18 pullRefs []models.ReferenceLink ··· 27 27 } 28 28 issueUris, err := findIssueReferences(e, issueRefs) 29 29 if err != nil { 30 - return nil, err 30 + return nil, fmt.Errorf("find issue references: %w", err) 31 31 } 32 32 pullUris, err := findPullReferences(e, pullRefs) 33 33 if err != nil { 34 - return nil, err 34 + return nil, fmt.Errorf("find pull references: %w", err) 35 35 } 36 36 37 37 return append(issueUris, pullUris...), nil ··· 124 124 ) 125 125 select 126 126 p.owner_did, p.rkey, 127 - c.owner_did, c.rkey 127 + c.comment_at 128 128 from input inp 129 129 join repos r 130 130 on r.did = inp.owner_did ··· 150 150 for rows.Next() { 151 151 // Scan rows 152 152 var pullOwner, pullRkey string 153 - var commentOwner, commentRkey sql.NullString 153 + var commentUri sql.NullString 154 154 var uri syntax.ATURI 155 - if err := rows.Scan(&pullOwner, &pullRkey, &commentOwner, &commentRkey); err != nil { 155 + if err := rows.Scan(&pullOwner, &pullRkey, &commentUri); err != nil { 156 156 return nil, err 157 157 } 158 - if commentOwner.Valid && commentRkey.Valid { 159 - uri = syntax.ATURI(fmt.Sprintf( 160 - "at://%s/%s/%s", 161 - commentOwner.String, 162 - tangled.RepoPullCommentNSID, 163 - commentRkey.String, 164 - )) 158 + if commentUri.Valid { 159 + // no-op 160 + uri = syntax.ATURI(commentUri.String) 165 161 } else { 166 162 uri = syntax.ATURI(fmt.Sprintf( 167 163 "at://%s/%s/%s", ··· 176 172 } 177 173 178 174 func putReferences(tx *sql.Tx, fromAt syntax.ATURI, references []syntax.ATURI) error { 175 + fmt.Println("insering references", references) 179 176 err := deleteReferences(tx, fromAt) 180 177 if err != nil { 181 - return fmt.Errorf("delete old references: %w", err) 178 + return fmt.Errorf("delete old reference_links: %w", err) 182 179 } 180 + if len(references) == 0 { 181 + return nil 182 + } 183 183 184 184 values := make([]string, 0, len(references)) 185 185 args := make([]any, 0, len(references)*2) ··· 189 189 } 190 190 _, err = tx.Exec( 191 191 fmt.Sprintf( 192 - `insert into references (from, at) 192 + `insert into reference_links (from_at, to_at) 193 193 values %s`, 194 194 strings.Join(values, ","), 195 195 ), 196 196 args..., 197 197 ) 198 198 if err != nil { 199 - return fmt.Errorf("insert new references: %w", err) 199 + return fmt.Errorf("insert new reference_links: %w", err) 200 200 } 201 201 return nil 202 202 } 203 203 204 204 func deleteReferences(tx *sql.Tx, fromAt syntax.ATURI) error { 205 - _, err := tx.Exec(`delete from references where from_at = ?`, fromAt) 205 + _, err := tx.Exec(`delete from reference_links where from_at = ?`, fromAt) 206 206 return err 207 207 } 208 208 ··· 223 223 224 224 rows, err := e.Query( 225 225 fmt.Sprintf( 226 - `select from_at, to_at from references %s`, 226 + `select from_at, to_at from reference_links %s`, 227 227 whereClause, 228 228 ), 229 + args..., 229 230 ) 230 231 if err != nil { 231 - return nil, fmt.Errorf("query references: %w", err) 232 + return nil, fmt.Errorf("query reference_links: %w", err) 232 233 } 233 234 defer rows.Close() 234 235
appview/ingester.go

This file has not been changed.

+6
appview/issues/issues.go
··· 472 472 rp.pages.Notice(w, "issue-comment", "Failed to create comment.") 473 473 return 474 474 } 475 + err = tx.Commit() 476 + if err != nil { 477 + l.Error("failed to commit transaction", "err", err) 478 + rp.pages.Notice(w, "issue-comment", "Failed to create comment, try again later.") 479 + return 480 + } 475 481 476 482 // reset atUri to make rollback a no-op 477 483 atUri = ""
+12
appview/models/issue.go
··· 229 229 return nil, err 230 230 } 231 231 232 + i := record 233 + mentions := make([]syntax.DID, len(record.Mentions)) 234 + for i, did := range record.Mentions { 235 + mentions[i] = syntax.DID(did) 236 + } 237 + references := make([]syntax.ATURI, len(record.References)) 238 + for i, uri := range i.References { 239 + references[i] = syntax.ATURI(uri) 240 + } 241 + 232 242 comment := IssueComment{ 233 243 Did: ownerDid, 234 244 Rkey: rkey, ··· 236 246 IssueAt: record.Issue, 237 247 ReplyTo: record.ReplyTo, 238 248 Created: created, 249 + Mentions: mentions, 250 + References: references, 239 251 } 240 252 241 253 return &comment, nil
appview/models/pull.go

This file has not been changed.

appview/pulls/pulls.go

This file has not been changed.

lexicons/issue/comment.json

This file has not been changed.

lexicons/issue/issue.json

This file has not been changed.

lexicons/pulls/comment.json

This file has not been changed.

+2 -2
appview/refresolver/resolver.go
··· 34 34 } 35 35 36 36 func (r *Resolver) Resolve(ctx context.Context, source string) ([]syntax.DID, []syntax.ATURI) { 37 - l := r.logger.With("method", "find_references") 37 + l := r.logger.With("method", "Resolve") 38 38 rawMentions, rawRefs := markup.FindReferences(r.config.Core.AppviewHost, source) 39 39 l.Debug("found possible references", "mentions", rawMentions, "refs", rawRefs) 40 40 idents := r.idResolver.ResolveIdents(ctx, rawMentions) ··· 55 55 rawRef.Handle = string(ident.DID) 56 56 resolvedRefs = append(resolvedRefs, rawRef) 57 57 } 58 - aturiRefs, err := db.FindReferences(r.execer, resolvedRefs) 58 + aturiRefs, err := db.ValidateReferenceLinks(r.execer, resolvedRefs) 59 59 if err != nil { 60 60 l.Error("failed running query", "err", err) 61 61 }

History

13 rounds 0 comments
sign up or login to add to the discussion
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 failed
expand
expand 0 comments
pull request successfully merged
1 commit
expand
appview,lexicons: atprotate the mentions & references
1/3 failed, 2/3 running
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 failed
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
1/3 failed, 2/3 timeout
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
1/3 failed, 2/3 timeout
expand
expand 0 comments
1 commit
expand
appview,lexicons: atprotate the mentions & references
3/3 success
expand
expand 0 comments