fix: bound opening a Chrome tab

Render bounds opening the tab and rendering the page with one deadline
(TabOpenTimeout 5 s plus RenderTimeout 20 s), so a hung Chrome no longer
holds the crawl's render lock until the job timeout.
This commit is contained in:
Jakub Zych
2026-11-04 22:53:40 +01:00
parent cd7182395f
commit cfeb3dff12
3 changed files with 101 additions and 9 deletions

View File

@@ -8,6 +8,7 @@ import (
"path/filepath"
"strings"
"testing"
"time"
"git.golem15.com/golem15/summercms/modules/compass"
)
@@ -124,3 +125,42 @@ func TestRenderMax(t *testing.T) {
t.Fatalf("SiteHosts = %v", got)
}
}
// TestRenderTabTimeout pins L3 WR-06: a tab that does not open answers an
// error within TabOpenTimeout (lowered for the test) plus a margin, so the
// crawl's render lock is released; the next Render is not held up by the
// first one's hung tab.
func TestRenderTabTimeout(t *testing.T) {
saved := TabOpenTimeout
TabOpenTimeout = 50 * time.Millisecond
t.Cleanup(func() { TabOpenTimeout = saved })
hung := make(chan struct{})
t.Cleanup(func() { close(hung) })
r := &chromeRenderer{
allowed: []string{"example.test"},
browserCtx: context.Background(),
newTab: func(parent context.Context) (context.Context, context.CancelFunc) {
return context.WithCancel(parent)
},
// A hung Chrome: opening the tab never answers, even when the tab
// is closed.
startTab: func(context.Context) error {
<-hung
return nil
},
}
for i := range 2 {
start := time.Now()
_, err := r.Render(t.Context(), "https://example.test/a")
if err == nil || !strings.Contains(err.Error(), "did not open a tab within 50ms") {
t.Fatalf("Render %d: %v, want the tab timeout", i, err)
}
if d := time.Since(start); d > time.Second {
t.Fatalf("Render %d returned after %v", i, d)
}
}
TabOpenTimeout = 5 * time.Second
if got := seconds(TabOpenTimeout); got != "5 s" {
t.Fatalf("seconds = %q", got)
}
}