Skip to content

Commit 5599d2a

Browse files
retlehsclaude
andauthored
Limit OG image generation concurrency (#47)
* Limit OG image generation to 2 concurrent goroutines Under heavy crawler traffic, unbounded OG generation goroutines were constantly contesting the SQLite write lock, starving the pipeline. Non-blocking semaphore skips generation when at capacity — the image will be generated on the next visit instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Move OG semaphore to call site to prevent goroutine churn Acquiring the semaphore before spawning the goroutine ensures excess requests under crawler spikes don't create unbounded goroutines that immediately exit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b71d4f5 commit 5599d2a

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

internal/http/handlers.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ import (
2929

3030
const perPage = 12
3131

32+
// ogSem limits concurrent OG image generation to avoid starving the pipeline
33+
// of DB write access under heavy crawler traffic.
34+
var ogSem = make(chan struct{}, 2)
35+
3236
// captureError reports a non-panic error to Sentry with the request's hub.
3337
// It silently ignores context cancellation errors (timeouts, client disconnects)
3438
// since these are expected during normal operation.
@@ -223,8 +227,15 @@ func handleDetail(a *app.App, tmpl *templateSet) http.HandlerFunc {
223227

224228
ogKey := "social/" + pkg.Type + "/" + pkg.Name + ".png"
225229
if pkg.OGImageGeneratedAt == nil {
226-
// Generate on demand in background
227-
go generatePackageOG(a, pkg)
230+
// Generate on demand in background (skip if at capacity)
231+
select {
232+
case ogSem <- struct{}{}:
233+
go func() {
234+
defer func() { <-ogSem }()
235+
generatePackageOG(a, pkg)
236+
}()
237+
default:
238+
}
228239
}
229240

230241
displayName := pkg.Name

0 commit comments

Comments
 (0)