Monorepo for Tangled tangled.org
2

Configure Feed

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

appview/db: scope reverse-mapping queries

multiple `defer rows.Close()` call in same scope can be dangerous as
underlying value will change.
avoid that by splitting reverse-mapping queries into scoped blocks.

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

author
Seongmin Lee
date (Jun 16, 2026, 11:31 PM +0900) commit 2359fa0c parent 09c38446 change-id xzloqzut
+142 -128
+142 -128
appview/db/repos.go
··· 207 207 } 208 208 209 209 // get labels for all repos 210 - labelsQuery := fmt.Sprintf( 211 - `select repo_did, label_at from repo_labels where repo_did in (%s)`, 212 - inClause, 213 - ) 210 + { 211 + labelsQuery := fmt.Sprintf( 212 + `select repo_did, label_at from repo_labels where repo_did in (%s)`, 213 + inClause, 214 + ) 214 215 215 - rows, err = e.Query(labelsQuery, args...) 216 - if err != nil { 217 - return nil, err 218 - } 219 - defer rows.Close() 216 + rows, err = e.Query(labelsQuery, args...) 217 + if err != nil { 218 + return nil, fmt.Errorf("failed to execute repo_labels query: %w", err) 219 + } 220 + defer rows.Close() 220 221 221 - for rows.Next() { 222 - var repoDid, labelat string 223 - if err := rows.Scan(&repoDid, &labelat); err != nil { 224 - continue 222 + for rows.Next() { 223 + var repoDid, labelat string 224 + if err := rows.Scan(&repoDid, &labelat); err != nil { 225 + log.Println("err", err) 226 + continue 227 + } 228 + if r, ok := repoMap[repoDid]; ok { 229 + r.Labels = append(r.Labels, labelat) 230 + } 225 231 } 226 - if r, ok := repoMap[repoDid]; ok { 227 - r.Labels = append(r.Labels, labelat) 232 + if err = rows.Err(); err != nil { 233 + return nil, fmt.Errorf("failed to execute repo_labels query: %w", err) 228 234 } 229 235 } 230 236 231 237 // get primary language for all repos 232 - languageQuery := fmt.Sprintf(` 233 - select repo_did, language 234 - from ( 235 - select 236 - repo_did, language, 237 - row_number() over ( 238 - partition by repo_did 239 - order by bytes desc 240 - ) as rn 241 - from repo_languages 242 - where repo_did in (%s) 243 - and is_default_ref = 1 244 - and language <> '' 245 - ) 246 - where rn = 1 247 - `, inClause) 238 + { 239 + languageQuery := fmt.Sprintf(` 240 + select repo_did, language 241 + from ( 242 + select 243 + repo_did, language, 244 + row_number() over ( 245 + partition by repo_did 246 + order by bytes desc 247 + ) as rn 248 + from repo_languages 249 + where repo_did in (%s) 250 + and is_default_ref = 1 251 + and language <> '' 252 + ) 253 + where rn = 1 254 + `, inClause) 248 255 249 - rows, err = e.Query(languageQuery, args...) 250 - if err != nil { 251 - return nil, fmt.Errorf("failed to execute lang query: %w", err) 252 - } 253 - defer rows.Close() 256 + rows, err = e.Query(languageQuery, args...) 257 + if err != nil { 258 + return nil, fmt.Errorf("failed to execute lang query: %w", err) 259 + } 260 + defer rows.Close() 254 261 255 - for rows.Next() { 256 - var repoDid, lang string 257 - if err := rows.Scan(&repoDid, &lang); err != nil { 258 - log.Println("err", "err", err) 259 - continue 262 + for rows.Next() { 263 + var repoDid, lang string 264 + if err := rows.Scan(&repoDid, &lang); err != nil { 265 + log.Println("err", err) 266 + continue 267 + } 268 + if r, ok := repoMap[repoDid]; ok { 269 + r.RepoStats.Language = lang 270 + } 260 271 } 261 - if r, ok := repoMap[repoDid]; ok { 262 - r.RepoStats.Language = lang 272 + if err = rows.Err(); err != nil { 273 + return nil, fmt.Errorf("failed to execute lang query: %w", err) 263 274 } 264 275 } 265 - if err = rows.Err(); err != nil { 266 - return nil, fmt.Errorf("failed to execute lang query: %w", err) 267 - } 268 276 269 277 // get star counts 270 - starCountQuery := fmt.Sprintf( 271 - `select subject, count(1) from stars where subject_type = 'repo' and subject in (%s) group by subject`, 272 - inClause, 273 - ) 278 + { 279 + starCountQuery := fmt.Sprintf( 280 + `select subject, count(1) from stars where subject_type = 'repo' and subject in (%s) group by subject`, 281 + inClause, 282 + ) 274 283 275 - rows, err = e.Query(starCountQuery, args...) 276 - if err != nil { 277 - return nil, fmt.Errorf("failed to execute star-count query: %w", err) 278 - } 279 - defer rows.Close() 284 + rows, err = e.Query(starCountQuery, args...) 285 + if err != nil { 286 + return nil, fmt.Errorf("failed to execute star-count query: %w", err) 287 + } 288 + defer rows.Close() 280 289 281 - for rows.Next() { 282 - var repoDid string 283 - var count int 284 - if err := rows.Scan(&repoDid, &count); err != nil { 285 - log.Println("err", "err", err) 286 - continue 290 + for rows.Next() { 291 + var repoDid string 292 + var count int 293 + if err := rows.Scan(&repoDid, &count); err != nil { 294 + log.Println("err", "err", err) 295 + continue 296 + } 297 + if r, ok := repoMap[repoDid]; ok { 298 + r.RepoStats.StarCount = count 299 + } 287 300 } 288 - if r, ok := repoMap[repoDid]; ok { 289 - r.RepoStats.StarCount = count 301 + if err = rows.Err(); err != nil { 302 + return nil, fmt.Errorf("failed to execute star-count query: %w", err) 290 303 } 291 304 } 292 - if err = rows.Err(); err != nil { 293 - return nil, fmt.Errorf("failed to execute star-count query: %w", err) 294 - } 295 305 296 306 // get issue counts 297 - issueCountQuery := fmt.Sprintf(` 298 - select 299 - repo_did, 300 - count(case when open = 1 then 1 end) as open_count, 301 - count(case when open = 0 then 1 end) as closed_count 302 - from issues 303 - where repo_did in (%s) 304 - group by repo_did 305 - `, inClause) 307 + { 308 + issueCountQuery := fmt.Sprintf(` 309 + select 310 + repo_did, 311 + count(case when open = 1 then 1 end) as open_count, 312 + count(case when open = 0 then 1 end) as closed_count 313 + from issues 314 + where repo_did in (%s) 315 + group by repo_did 316 + `, inClause) 306 317 307 - rows, err = e.Query(issueCountQuery, args...) 308 - if err != nil { 309 - return nil, fmt.Errorf("failed to execute issue-count query: %w", err) 310 - } 311 - defer rows.Close() 318 + rows, err = e.Query(issueCountQuery, args...) 319 + if err != nil { 320 + return nil, fmt.Errorf("failed to execute issue-count query: %w", err) 321 + } 322 + defer rows.Close() 312 323 313 - for rows.Next() { 314 - var repoDid string 315 - var open, closed int 316 - if err := rows.Scan(&repoDid, &open, &closed); err != nil { 317 - log.Println("err", "err", err) 318 - continue 324 + for rows.Next() { 325 + var repoDid string 326 + var open, closed int 327 + if err := rows.Scan(&repoDid, &open, &closed); err != nil { 328 + log.Println("err", err) 329 + continue 330 + } 331 + if r, ok := repoMap[repoDid]; ok { 332 + r.RepoStats.IssueCount.Open = open 333 + r.RepoStats.IssueCount.Closed = closed 334 + } 319 335 } 320 - if r, ok := repoMap[repoDid]; ok { 321 - r.RepoStats.IssueCount.Open = open 322 - r.RepoStats.IssueCount.Closed = closed 336 + if err = rows.Err(); err != nil { 337 + return nil, fmt.Errorf("failed to execute issue-count query: %w", err) 323 338 } 324 339 } 325 - if err = rows.Err(); err != nil { 326 - return nil, fmt.Errorf("failed to execute issue-count query: %w", err) 327 - } 328 340 329 341 // get pull counts 330 - pullCountQuery := fmt.Sprintf(` 331 - select 332 - repo_did, 333 - count(case when state = ? then 1 end) as open_count, 334 - count(case when state = ? then 1 end) as merged_count, 335 - count(case when state = ? then 1 end) as closed_count, 336 - count(case when state = ? then 1 end) as deleted_count 337 - from pulls 338 - where repo_did in (%s) 339 - group by repo_did 340 - `, inClause) 342 + { 343 + pullCountQuery := fmt.Sprintf(` 344 + select 345 + repo_did, 346 + count(case when state = ? then 1 end) as open_count, 347 + count(case when state = ? then 1 end) as merged_count, 348 + count(case when state = ? then 1 end) as closed_count, 349 + count(case when state = ? then 1 end) as deleted_count 350 + from pulls 351 + where repo_did in (%s) 352 + group by repo_did 353 + `, inClause) 341 354 342 - pullArgs := append([]any{ 343 - models.PullOpen, 344 - models.PullMerged, 345 - models.PullClosed, 346 - models.PullAbandoned, 347 - }, args...) 355 + pullArgs := append([]any{ 356 + models.PullOpen, 357 + models.PullMerged, 358 + models.PullClosed, 359 + models.PullAbandoned, 360 + }, args...) 348 361 349 - rows, err = e.Query(pullCountQuery, pullArgs...) 350 - if err != nil { 351 - return nil, fmt.Errorf("failed to execute pulls-count query: %w", err) 352 - } 353 - defer rows.Close() 362 + rows, err = e.Query(pullCountQuery, pullArgs...) 363 + if err != nil { 364 + return nil, fmt.Errorf("failed to execute pulls-count query: %w", err) 365 + } 366 + defer rows.Close() 354 367 355 - for rows.Next() { 356 - var repoDid string 357 - var open, merged, closed, deleted int 358 - if err := rows.Scan(&repoDid, &open, &merged, &closed, &deleted); err != nil { 359 - log.Println("err", "err", err) 360 - continue 368 + for rows.Next() { 369 + var repoDid string 370 + var open, merged, closed, deleted int 371 + if err := rows.Scan(&repoDid, &open, &merged, &closed, &deleted); err != nil { 372 + log.Println("err", "err", err) 373 + continue 374 + } 375 + if r, ok := repoMap[repoDid]; ok { 376 + r.RepoStats.PullCount.Open = open 377 + r.RepoStats.PullCount.Merged = merged 378 + r.RepoStats.PullCount.Closed = closed 379 + r.RepoStats.PullCount.Deleted = deleted 380 + } 361 381 } 362 - if r, ok := repoMap[repoDid]; ok { 363 - r.RepoStats.PullCount.Open = open 364 - r.RepoStats.PullCount.Merged = merged 365 - r.RepoStats.PullCount.Closed = closed 366 - r.RepoStats.PullCount.Deleted = deleted 382 + if err = rows.Err(); err != nil { 383 + return nil, fmt.Errorf("failed to execute pulls-count query: %w", err) 367 384 } 368 - } 369 - if err = rows.Err(); err != nil { 370 - return nil, fmt.Errorf("failed to execute pulls-count query: %w", err) 371 385 } 372 386 373 387 // get forks — only query repos with a non-empty repo_did, since source