Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

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

appview/db: introduce GetReposPaginated

also reimplement GetRepos in terms of GetReposPaginated

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

authored by

oppiliappan and committed by tangled.org 8392f026 3cbb51a0

+83 -85
+1 -1
appview/db/collaborators.go
··· 59 59 return nil, nil 60 60 } 61 61 62 - return GetRepos(e, 0, orm.FilterIn("at_uri", repoAts)) 62 + return GetRepos(e, orm.FilterIn("at_uri", repoAts)) 63 63 } 64 64 65 65 func GetCollaborators(e Execer, filters ...orm.Filter) ([]models.Collaborator, error) {
+1 -1
appview/db/issues.go
··· 206 206 repoAts = append(repoAts, string(issue.RepoAt)) 207 207 } 208 208 209 - repos, err := GetRepos(e, 0, orm.FilterIn("at_uri", repoAts)) 209 + repos, err := GetRepos(e, orm.FilterIn("at_uri", repoAts)) 210 210 if err != nil { 211 211 return nil, fmt.Errorf("failed to build repo mappings: %w", err) 212 212 }
+2 -2
appview/db/profile.go
··· 66 66 *items = append(*items, &issue) 67 67 } 68 68 69 - repos, err := GetRepos(e, 0, orm.FilterEq("did", forDid)) 69 + repos, err := GetRepos(e, orm.FilterEq("did", forDid)) 70 70 if err != nil { 71 71 return nil, fmt.Errorf("error getting all repos by did: %w", err) 72 72 } ··· 489 489 } 490 490 491 491 // ensure all pinned repos are either own repos or collaborating repos 492 - repos, err := GetRepos(e, 0, orm.FilterEq("did", profile.Did)) 492 + repos, err := GetRepos(e, orm.FilterEq("did", profile.Did)) 493 493 if err != nil { 494 494 log.Printf("getting repos for %s: %s", profile.Did, err) 495 495 }
+1 -1
appview/db/pulls.go
··· 264 264 sourceAts = append(sourceAts, *p.PullSource.RepoAt) 265 265 } 266 266 } 267 - sourceRepos, err := GetRepos(e, 0, orm.FilterIn("at_uri", sourceAts)) 267 + sourceRepos, err := GetRepos(e, orm.FilterIn("at_uri", sourceAts)) 268 268 if err != nil && !errors.Is(err, sql.ErrNoRows) { 269 269 return nil, fmt.Errorf("failed to get source repos: %w", err) 270 270 }
+72 -67
appview/db/repos.go
··· 11 11 12 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 13 "tangled.org/core/appview/models" 14 + "tangled.org/core/appview/pagination" 14 15 "tangled.org/core/orm" 15 16 ) 16 17 17 - func GetRepos(e Execer, limit int, filters ...orm.Filter) ([]models.Repo, error) { 18 - repoMap := make(map[syntax.ATURI]*models.Repo) 18 + func GetRepos(e Execer, filters ...orm.Filter) ([]models.Repo, error) { 19 + return GetReposPaginated(e, pagination.Page{}, filters...) 20 + } 19 21 22 + func GetReposPaginated(e Execer, page pagination.Page, filters ...orm.Filter) ([]models.Repo, error) { 20 23 var conditions []string 21 24 var args []any 22 25 for _, filter := range filters { ··· 32 29 whereClause = " where " + strings.Join(conditions, " and ") 33 30 } 34 31 35 - limitClause := "" 36 - if limit != 0 { 37 - limitClause = fmt.Sprintf(" limit %d", limit) 32 + pageClause := "" 33 + if page.Limit != 0 { 34 + pageClause = fmt.Sprintf(" limit %d offset %d", page.Limit, page.Offset) 38 35 } 39 36 40 - repoQuery := fmt.Sprintf( 41 - `select 37 + // main query to get repos with pagination 38 + query := fmt.Sprintf(` 39 + select 42 40 id, 43 41 did, 44 42 name, ··· 51 47 topics, 52 48 source, 53 49 spindle 54 - from 55 - repos r 50 + from repos 56 51 %s 57 52 order by created desc 58 - %s`, 59 - whereClause, 60 - limitClause, 61 - ) 62 - rows, err := e.Query(repoQuery, args...) 53 + %s 54 + `, whereClause, pageClause) 55 + 56 + rows, err := e.Query(query, args...) 63 57 if err != nil { 64 - return nil, fmt.Errorf("failed to execute repo query: %w ", err) 58 + return nil, err 65 59 } 66 60 defer rows.Close() 67 61 62 + repoMap := make(map[syntax.ATURI]*models.Repo) 68 63 for rows.Next() { 69 64 var repo models.Repo 70 65 var createdAt string ··· 83 80 &spindle, 84 81 ) 85 82 if err != nil { 86 - return nil, fmt.Errorf("failed to execute repo query: %w ", err) 83 + return nil, err 87 84 } 88 85 86 + // parse created timestamp 89 87 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 90 88 repo.Created = t 91 89 } 90 + 91 + // handle nullable fields 92 92 if description.Valid { 93 93 repo.Description = description.String 94 94 } ··· 113 107 } 114 108 115 109 if err = rows.Err(); err != nil { 116 - return nil, fmt.Errorf("failed to execute repo query: %w ", err) 110 + return nil, err 117 111 } 118 112 113 + // if no repos, return early 114 + if len(repoMap) == 0 { 115 + return nil, nil 116 + } 117 + 118 + // build IN clause for related queries 119 119 inClause := strings.TrimSuffix(strings.Repeat("?, ", len(repoMap)), ", ") 120 120 args = make([]any, len(repoMap)) 121 - 122 121 i := 0 123 122 for _, r := range repoMap { 124 123 args[i] = r.RepoAt() 125 124 i++ 126 125 } 127 126 128 - // Get labels for all repos 127 + // get labels for all repos 129 128 labelsQuery := fmt.Sprintf( 130 129 `select repo_at, label_at from repo_labels where repo_at in (%s)`, 131 130 inClause, 132 131 ) 132 + 133 133 rows, err = e.Query(labelsQuery, args...) 134 134 if err != nil { 135 - return nil, fmt.Errorf("failed to execute labels query: %w ", err) 135 + return nil, err 136 136 } 137 137 defer rows.Close() 138 138 139 139 for rows.Next() { 140 140 var repoat, labelat string 141 141 if err := rows.Scan(&repoat, &labelat); err != nil { 142 - log.Println("err", "err", err) 143 142 continue 144 143 } 145 144 if r, ok := repoMap[syntax.ATURI(repoat)]; ok { 146 145 r.Labels = append(r.Labels, labelat) 147 146 } 148 147 } 149 - if err = rows.Err(); err != nil { 150 - return nil, fmt.Errorf("failed to execute labels query: %w ", err) 151 - } 152 148 153 - languageQuery := fmt.Sprintf( 154 - ` 149 + // get primary language for all repos 150 + languageQuery := fmt.Sprintf(` 155 151 select repo_at, language 156 152 from ( 157 153 select 158 - repo_at, 159 - language, 160 - row_number() over ( 161 - partition by repo_at 162 - order by bytes desc 163 - ) as rn 154 + repo_at, language, 155 + row_number() over ( 156 + partition by repo_at 157 + order by bytes desc 158 + ) as rn 164 159 from repo_languages 165 160 where repo_at in (%s) 166 - and is_default_ref = 1 167 - and language <> '' 161 + and is_default_ref = 1 162 + and language <> '' 168 163 ) 169 164 where rn = 1 170 - `, 171 - inClause, 172 - ) 165 + `, inClause) 166 + 173 167 rows, err = e.Query(languageQuery, args...) 174 168 if err != nil { 175 - return nil, fmt.Errorf("failed to execute lang query: %w ", err) 169 + return nil, fmt.Errorf("failed to execute lang query: %w", err) 176 170 } 177 171 defer rows.Close() 178 172 ··· 187 181 } 188 182 } 189 183 if err = rows.Err(); err != nil { 190 - return nil, fmt.Errorf("failed to execute lang query: %w ", err) 184 + return nil, fmt.Errorf("failed to execute lang query: %w", err) 191 185 } 192 186 187 + // get star counts 193 188 starCountQuery := fmt.Sprintf( 194 - `select 195 - subject_at, count(1) 196 - from stars 197 - where subject_at in (%s) 198 - group by subject_at`, 189 + `select subject_at, count(1) from stars where subject_at in (%s) group by subject_at`, 199 190 inClause, 200 191 ) 192 + 201 193 rows, err = e.Query(starCountQuery, args...) 202 194 if err != nil { 203 - return nil, fmt.Errorf("failed to execute star-count query: %w ", err) 195 + return nil, fmt.Errorf("failed to execute star-count query: %w", err) 204 196 } 205 197 defer rows.Close() 206 198 ··· 214 210 } 215 211 } 216 212 if err = rows.Err(); err != nil { 217 - return nil, fmt.Errorf("failed to execute star-count query: %w ", err) 213 + return nil, fmt.Errorf("failed to execute star-count query: %w", err) 218 214 } 219 215 220 - issueCountQuery := fmt.Sprintf( 221 - `select 216 + // get issue counts 217 + issueCountQuery := fmt.Sprintf(` 218 + select 222 219 repo_at, 223 220 count(case when open = 1 then 1 end) as open_count, 224 221 count(case when open = 0 then 1 end) as closed_count 225 222 from issues 226 223 where repo_at in (%s) 227 - group by repo_at`, 228 - inClause, 229 - ) 224 + group by repo_at 225 + `, inClause) 226 + 230 227 rows, err = e.Query(issueCountQuery, args...) 231 228 if err != nil { 232 - return nil, fmt.Errorf("failed to execute issue-count query: %w ", err) 229 + return nil, fmt.Errorf("failed to execute issue-count query: %w", err) 233 230 } 234 231 defer rows.Close() 235 232 ··· 247 242 } 248 243 } 249 244 if err = rows.Err(); err != nil { 250 - return nil, fmt.Errorf("failed to execute issue-count query: %w ", err) 245 + return nil, fmt.Errorf("failed to execute issue-count query: %w", err) 251 246 } 252 247 253 - pullCountQuery := fmt.Sprintf( 254 - `select 248 + // get pull counts 249 + pullCountQuery := fmt.Sprintf(` 250 + select 255 251 repo_at, 256 252 count(case when state = ? then 1 end) as open_count, 257 253 count(case when state = ? then 1 end) as merged_count, ··· 260 254 count(case when state = ? then 1 end) as deleted_count 261 255 from pulls 262 256 where repo_at in (%s) 263 - group by repo_at`, 264 - inClause, 265 - ) 266 - args = append([]any{ 257 + group by repo_at 258 + `, inClause) 259 + 260 + pullArgs := append([]any{ 267 261 models.PullOpen, 268 262 models.PullMerged, 269 263 models.PullClosed, 270 264 models.PullDeleted, 271 265 }, args...) 272 - rows, err = e.Query( 273 - pullCountQuery, 274 - args..., 275 - ) 266 + 267 + rows, err = e.Query(pullCountQuery, pullArgs...) 276 268 if err != nil { 277 - return nil, fmt.Errorf("failed to execute pulls-count query: %w ", err) 269 + return nil, fmt.Errorf("failed to execute pulls-count query: %w", err) 278 270 } 279 271 defer rows.Close() 280 272 ··· 291 287 } 292 288 } 293 289 if err = rows.Err(); err != nil { 294 - return nil, fmt.Errorf("failed to execute pulls-count query: %w ", err) 290 + return nil, fmt.Errorf("failed to execute pulls-count query: %w", err) 295 291 } 296 292 297 293 var repos []models.Repo ··· 299 295 repos = append(repos, *r) 300 296 } 301 297 298 + // sort by created timestamp (desc) 302 299 slices.SortFunc(repos, func(a, b models.Repo) int { 303 300 if a.Created.After(b.Created) { 304 301 return -1 ··· 312 307 313 308 // helper to get exactly one repo 314 309 func GetRepo(e Execer, filters ...orm.Filter) (*models.Repo, error) { 315 - repos, err := GetRepos(e, 0, filters...) 310 + repos, err := GetReposPaginated(e, pagination.Page{Limit: 1}, filters...) 316 311 if err != nil { 317 312 return nil, err 318 313 } ··· 322 317 } 323 318 324 319 if len(repos) != 1 { 325 - return nil, fmt.Errorf("too many rows returned") 320 + return nil, fmt.Errorf("too few rows returned") 326 321 } 327 322 328 323 return &repos[0], nil
+2 -2
appview/db/star.go
··· 197 197 return nil, nil 198 198 } 199 199 200 - repos, err := GetRepos(e, 0, orm.FilterIn("at_uri", args)) 200 + repos, err := GetRepos(e, orm.FilterIn("at_uri", args)) 201 201 if err != nil { 202 202 return nil, err 203 203 } ··· 300 300 } 301 301 302 302 // get full repo data 303 - repos, err := GetRepos(e, 0, orm.FilterIn("at_uri", repoUris)) 303 + repos, err := GetRepos(e, orm.FilterIn("at_uri", repoUris)) 304 304 if err != nil { 305 305 return nil, err 306 306 }
+3 -2
appview/db/timeline.go
··· 5 5 6 6 "github.com/bluesky-social/indigo/atproto/syntax" 7 7 "tangled.org/core/appview/models" 8 + "tangled.org/core/appview/pagination" 8 9 "tangled.org/core/orm" 9 10 ) 10 11 ··· 91 90 filters = append(filters, orm.FilterIn("did", userIsFollowing)) 92 91 } 93 92 94 - repos, err := GetRepos(e, limit, filters...) 93 + repos, err := GetReposPaginated(e, pagination.Page{Limit: limit}, filters...) 95 94 if err != nil { 96 95 return nil, err 97 96 } ··· 106 105 107 106 var origRepos []models.Repo 108 107 if args != nil { 109 - origRepos, err = GetRepos(e, 0, orm.FilterIn("at_uri", args)) 108 + origRepos, err = GetRepos(e, orm.FilterIn("at_uri", args)) 110 109 } 111 110 if err != nil { 112 111 return nil, err
-1
appview/knots/knots.go
··· 112 112 113 113 repos, err := db.GetRepos( 114 114 k.Db, 115 - 0, 116 115 orm.FilterEq("knot", domain), 117 116 ) 118 117 if err != nil {
-1
appview/spindles/spindles.go
··· 109 109 110 110 repos, err := db.GetRepos( 111 111 s.Db, 112 - 0, 113 112 orm.FilterEq("spindle", instance), 114 113 ) 115 114 if err != nil {
-4
appview/state/knotstream.go
··· 107 107 var errWebhook error 108 108 repos, err := db.GetRepos( 109 109 d, 110 - 0, 111 110 orm.FilterEq("did", record.RepoDid), 112 111 orm.FilterEq("name", record.RepoName), 113 112 ) ··· 148 149 149 150 repos, err := db.GetRepos( 150 151 d, 151 - 0, 152 152 orm.FilterEq("did", record.RepoDid), 153 153 orm.FilterEq("name", record.RepoName), 154 154 ) ··· 239 241 240 242 repos, err := db.GetRepos( 241 243 d, 242 - 0, 243 244 orm.FilterEq("did", record.RepoDid), 244 245 orm.FilterEq("name", record.RepoName), 245 246 ) ··· 304 307 // does this repo have a spindle configured? 305 308 repos, err := db.GetRepos( 306 309 d, 307 - 0, 308 310 orm.FilterEq("did", record.TriggerMetadata.Repo.Did), 309 311 orm.FilterEq("name", record.TriggerMetadata.Repo.Repo), 310 312 )
+1 -3
appview/state/profile.go
··· 139 139 140 140 repos, err := db.GetRepos( 141 141 s.db, 142 - 0, 143 142 orm.FilterEq("did", profile.UserDid), 144 143 ) 145 144 if err != nil { ··· 230 231 231 232 repos, err := db.GetRepos( 232 233 s.db, 233 - 0, 234 234 orm.FilterEq("did", profile.UserDid), 235 235 ) 236 236 if err != nil { ··· 747 749 profile = &models.Profile{Did: user.Active.Did} 748 750 } 749 751 750 - repos, err := db.GetRepos(s.db, 0, orm.FilterEq("did", user.Active.Did)) 752 + repos, err := db.GetRepos(s.db, orm.FilterEq("did", user.Active.Did)) 751 753 if err != nil { 752 754 log.Printf("getting repos for %s: %s", user.Active.Did, err) 753 755 }