detached 7a7144e

refactor(webview-pool): pass context as first parameter instead of storing

Remove stored ctx field from WebViewPool and update all methods
(Acquire, createWebView, Release, Prewarm, Close) to accept context as
first parameter, following project convention of using
log := logging.FromContext(ctx) in each method.
commit
7a7144eeaadfbe9bfe2bd6c2fe0efab3d453decb
author
brice · · 2025-12-17 06:44 UTC
parent
401b02c
signature
unsigned
1 file · +21 -20
M internal/infrastructure/webkit/pool.go +21 -20
@@ -38,7 +38,6 @@ type WebViewPool struct {
3838 config PoolConfig
3939
4040 pool chan *WebView
41- ctx context.Context
4241 injector *ContentInjector
4342 router *MessageRouter
4443
@@ -66,17 +65,19 @@ func NewWebViewPool(ctx context.Context, wkCtx *WebKitContext, settings *Setting
6665 settings: settings,
6766 config: cfg,
6867 pool: make(chan *WebView, cfg.MaxSize),
69- ctx: logging.WithComponent(ctx, "webview-pool"),
7068 injector: injector,
7169 router: router,
7270 }
7371
72+ log := logging.FromContext(ctx)
73+ log.Debug().Msg("creating webview pool")
74+
7475 return p
7576 }
7677
7778 // Acquire gets a WebView from the pool or creates a new one.
7879 func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
79- log := logging.FromContext(p.ctx)
80+ log := logging.FromContext(ctx)
8081
8182 if p.closed.Load() {
8283 return nil, context.Canceled
@@ -87,7 +88,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
8788 case wv := <-p.pool:
8889 if wv != nil && !wv.IsDestroyed() {
8990 // Ensure frontend is attached even if this WebView was pooled before injection was configured.
90- _ = wv.AttachFrontend(p.ctx, p.injector, p.router)
91+ _ = wv.AttachFrontend(ctx, p.injector, p.router)
9192 log.Debug().Uint64("id", uint64(wv.ID())).Msg("acquired webview from pool")
9293 return wv, nil
9394 }
@@ -98,13 +99,13 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
9899
99100 // Pool empty or pooled view was destroyed, create new
100101 log.Debug().Msg("pool empty, creating new webview")
101- return p.createWebView()
102+ return p.createWebView(ctx)
102103 }
103104
104-func (p *WebViewPool) createWebView() (*WebView, error) {
105- log := logging.FromContext(p.ctx)
105+func (p *WebViewPool) createWebView(ctx context.Context) (*WebView, error) {
106+ log := logging.FromContext(ctx)
106107
107- wv, err := NewWebView(p.ctx, p.wkCtx, p.settings)
108+ wv, err := NewWebView(ctx, p.wkCtx, p.settings)
108109 if err != nil {
109110 return nil, err
110111 }
@@ -112,7 +113,7 @@ func (p *WebViewPool) createWebView() (*WebView, error) {
112113 // Ensure WebView is visible when used
113114 wv.inner.SetVisible(true)
114115
115- if err := wv.AttachFrontend(p.ctx, p.injector, p.router); err != nil {
116+ if err := wv.AttachFrontend(ctx, p.injector, p.router); err != nil {
116117 log.Warn().Err(err).Msg("failed to attach frontend to new webview")
117118 }
118119
@@ -121,7 +122,9 @@ func (p *WebViewPool) createWebView() (*WebView, error) {
121122
122123 // Release returns a WebView to the pool.
123124 // The WebView is reset to about:blank before being pooled.
124-func (p *WebViewPool) Release(wv *WebView) {
125+func (p *WebViewPool) Release(ctx context.Context, wv *WebView) {
126+ log := logging.FromContext(ctx)
127+
125128 if wv == nil || wv.IsDestroyed() || p.closed.Load() {
126129 if wv != nil && !wv.IsDestroyed() {
127130 wv.Destroy()
@@ -130,7 +133,7 @@ func (p *WebViewPool) Release(wv *WebView) {
130133 }
131134
132135 // Reset to blank state
133- _ = wv.LoadURI(p.ctx, "about:blank")
136+ _ = wv.LoadURI(ctx, "about:blank")
134137
135138 // Clear callbacks
136139 wv.OnLoadChanged = nil
@@ -139,8 +142,6 @@ func (p *WebViewPool) Release(wv *WebView) {
139142 wv.OnProgressChanged = nil
140143 wv.OnClose = nil
141144
142- log := logging.FromContext(p.ctx)
143-
144145 // Try to return to pool (non-blocking)
145146 select {
146147 case p.pool <- wv:
@@ -154,19 +155,19 @@ func (p *WebViewPool) Release(wv *WebView) {
154155
155156 // Prewarm creates WebViews synchronously to populate the pool.
156157 // Must be called from the GTK main thread (after GTK application is initialized).
157-func (p *WebViewPool) Prewarm(count int) {
158+func (p *WebViewPool) Prewarm(ctx context.Context, count int) {
158159 if count <= 0 {
159160 count = p.config.PrewarmCount
160161 }
161162 if count <= 0 {
162163 return
163164 }
164- p.prewarmSync(count)
165+ p.prewarmSync(ctx, count)
165166 }
166167
167168 // prewarmSync creates WebViews synchronously.
168-func (p *WebViewPool) prewarmSync(count int) {
169- log := logging.FromContext(p.ctx)
169+func (p *WebViewPool) prewarmSync(ctx context.Context, count int) {
170+ log := logging.FromContext(ctx)
170171
171172 for i := 0; i < count && !p.closed.Load(); i++ {
172173 // Check if pool is already at capacity
@@ -174,7 +175,7 @@ func (p *WebViewPool) prewarmSync(count int) {
174175 break
175176 }
176177
177- wv, err := p.createWebView()
178+ wv, err := p.createWebView(ctx)
178179 if err != nil {
179180 log.Warn().Err(err).Msg("failed to prewarm webview")
180181 continue
@@ -201,12 +202,12 @@ func (p *WebViewPool) Size() int {
201202 }
202203
203204 // Close shuts down the pool and destroys all pooled WebViews.
204-func (p *WebViewPool) Close() {
205+func (p *WebViewPool) Close(ctx context.Context) {
205206 if p.closed.Swap(true) {
206207 return // Already closed
207208 }
208209
209- log := logging.FromContext(p.ctx)
210+ log := logging.FromContext(ctx)
210211
211212 // Wait for any background operations
212213 p.wg.Wait()
@@ -38,7 +38,6 @@ type WebViewPool struct {
38 config PoolConfig38 config PoolConfig
39 39
40 pool chan *WebView40 pool chan *WebView
41- ctx context.Context
42 injector *ContentInjector41 injector *ContentInjector
43 router *MessageRouter42 router *MessageRouter
44 43
@@ -66,17 +65,19 @@ func NewWebViewPool(ctx context.Context, wkCtx *WebKitContext, settings *Setting
66 settings: settings,65 settings: settings,
67 config: cfg,66 config: cfg,
68 pool: make(chan *WebView, cfg.MaxSize),67 pool: make(chan *WebView, cfg.MaxSize),
69- ctx: logging.WithComponent(ctx, "webview-pool"),
70 injector: injector,68 injector: injector,
71 router: router,69 router: router,
72 }70 }
73 71
72+ log := logging.FromContext(ctx)
73+ log.Debug().Msg("creating webview pool")
74+
74 return p75 return p
75 }76 }
76 77
77 // Acquire gets a WebView from the pool or creates a new one.78 // Acquire gets a WebView from the pool or creates a new one.
78 func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {79 func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
79- log := logging.FromContext(p.ctx)80+ log := logging.FromContext(ctx)
80 81
81 if p.closed.Load() {82 if p.closed.Load() {
82 return nil, context.Canceled83 return nil, context.Canceled
@@ -87,7 +88,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
87 case wv := <-p.pool:88 case wv := <-p.pool:
88 if wv != nil && !wv.IsDestroyed() {89 if wv != nil && !wv.IsDestroyed() {
89 // Ensure frontend is attached even if this WebView was pooled before injection was configured.90 // Ensure frontend is attached even if this WebView was pooled before injection was configured.
90- _ = wv.AttachFrontend(p.ctx, p.injector, p.router)91+ _ = wv.AttachFrontend(ctx, p.injector, p.router)
91 log.Debug().Uint64("id", uint64(wv.ID())).Msg("acquired webview from pool")92 log.Debug().Uint64("id", uint64(wv.ID())).Msg("acquired webview from pool")
92 return wv, nil93 return wv, nil
93 }94 }
@@ -98,13 +99,13 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) {
98 99
99 // Pool empty or pooled view was destroyed, create new100 // Pool empty or pooled view was destroyed, create new
100 log.Debug().Msg("pool empty, creating new webview")101 log.Debug().Msg("pool empty, creating new webview")
101- return p.createWebView()102+ return p.createWebView(ctx)
102 }103 }
103 104
104-func (p *WebViewPool) createWebView() (*WebView, error) {105+func (p *WebViewPool) createWebView(ctx context.Context) (*WebView, error) {
105- log := logging.FromContext(p.ctx)106+ log := logging.FromContext(ctx)
106 107
107- wv, err := NewWebView(p.ctx, p.wkCtx, p.settings)108+ wv, err := NewWebView(ctx, p.wkCtx, p.settings)
108 if err != nil {109 if err != nil {
109 return nil, err110 return nil, err
110 }111 }
@@ -112,7 +113,7 @@ func (p *WebViewPool) createWebView() (*WebView, error) {
112 // Ensure WebView is visible when used113 // Ensure WebView is visible when used
113 wv.inner.SetVisible(true)114 wv.inner.SetVisible(true)
114 115
115- if err := wv.AttachFrontend(p.ctx, p.injector, p.router); err != nil {116+ if err := wv.AttachFrontend(ctx, p.injector, p.router); err != nil {
116 log.Warn().Err(err).Msg("failed to attach frontend to new webview")117 log.Warn().Err(err).Msg("failed to attach frontend to new webview")
117 }118 }
118 119
@@ -121,7 +122,9 @@ func (p *WebViewPool) createWebView() (*WebView, error) {
121 122
122 // Release returns a WebView to the pool.123 // Release returns a WebView to the pool.
123 // The WebView is reset to about:blank before being pooled.124 // The WebView is reset to about:blank before being pooled.
124-func (p *WebViewPool) Release(wv *WebView) {125+func (p *WebViewPool) Release(ctx context.Context, wv *WebView) {
126+ log := logging.FromContext(ctx)
127+
125 if wv == nil || wv.IsDestroyed() || p.closed.Load() {128 if wv == nil || wv.IsDestroyed() || p.closed.Load() {
126 if wv != nil && !wv.IsDestroyed() {129 if wv != nil && !wv.IsDestroyed() {
127 wv.Destroy()130 wv.Destroy()
@@ -130,7 +133,7 @@ func (p *WebViewPool) Release(wv *WebView) {
130 }133 }
131 134
132 // Reset to blank state135 // Reset to blank state
133- _ = wv.LoadURI(p.ctx, "about:blank")136+ _ = wv.LoadURI(ctx, "about:blank")
134 137
135 // Clear callbacks138 // Clear callbacks
136 wv.OnLoadChanged = nil139 wv.OnLoadChanged = nil
@@ -139,8 +142,6 @@ func (p *WebViewPool) Release(wv *WebView) {
139 wv.OnProgressChanged = nil142 wv.OnProgressChanged = nil
140 wv.OnClose = nil143 wv.OnClose = nil
141 144
142- log := logging.FromContext(p.ctx)
143-
144 // Try to return to pool (non-blocking)145 // Try to return to pool (non-blocking)
145 select {146 select {
146 case p.pool <- wv:147 case p.pool <- wv:
@@ -154,19 +155,19 @@ func (p *WebViewPool) Release(wv *WebView) {
154 155
155 // Prewarm creates WebViews synchronously to populate the pool.156 // Prewarm creates WebViews synchronously to populate the pool.
156 // Must be called from the GTK main thread (after GTK application is initialized).157 // Must be called from the GTK main thread (after GTK application is initialized).
157-func (p *WebViewPool) Prewarm(count int) {158+func (p *WebViewPool) Prewarm(ctx context.Context, count int) {
158 if count <= 0 {159 if count <= 0 {
159 count = p.config.PrewarmCount160 count = p.config.PrewarmCount
160 }161 }
161 if count <= 0 {162 if count <= 0 {
162 return163 return
163 }164 }
164- p.prewarmSync(count)165+ p.prewarmSync(ctx, count)
165 }166 }
166 167
167 // prewarmSync creates WebViews synchronously.168 // prewarmSync creates WebViews synchronously.
168-func (p *WebViewPool) prewarmSync(count int) {169+func (p *WebViewPool) prewarmSync(ctx context.Context, count int) {
169- log := logging.FromContext(p.ctx)170+ log := logging.FromContext(ctx)
170 171
171 for i := 0; i < count && !p.closed.Load(); i++ {172 for i := 0; i < count && !p.closed.Load(); i++ {
172 // Check if pool is already at capacity173 // Check if pool is already at capacity
@@ -174,7 +175,7 @@ func (p *WebViewPool) prewarmSync(count int) {
174 break175 break
175 }176 }
176 177
177- wv, err := p.createWebView()178+ wv, err := p.createWebView(ctx)
178 if err != nil {179 if err != nil {
179 log.Warn().Err(err).Msg("failed to prewarm webview")180 log.Warn().Err(err).Msg("failed to prewarm webview")
180 continue181 continue
@@ -201,12 +202,12 @@ func (p *WebViewPool) Size() int {
201 }202 }
202 203
203 // Close shuts down the pool and destroys all pooled WebViews.204 // Close shuts down the pool and destroys all pooled WebViews.
204-func (p *WebViewPool) Close() {205+func (p *WebViewPool) Close(ctx context.Context) {
205 if p.closed.Swap(true) {206 if p.closed.Swap(true) {
206 return // Already closed207 return // Already closed
207 }208 }
208 209
209- log := logging.FromContext(p.ctx)210+ log := logging.FromContext(ctx)
210 211
211 // Wait for any background operations212 // Wait for any background operations
212 p.wg.Wait()213 p.wg.Wait()

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close