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 { | |||
| 38 | 38 | config PoolConfig | |
| 39 | 39 | ||
| 40 | 40 | pool chan *WebView | |
| 41 | - | ctx context.Context | |
| 42 | 41 | injector *ContentInjector | |
| 43 | 42 | router *MessageRouter | |
| 44 | 43 | ||
| @@ -66,17 +65,19 @@ func NewWebViewPool(ctx context.Context, wkCtx *WebKitContext, settings *Setting | |||
| 66 | 65 | settings: settings, | |
| 67 | 66 | config: cfg, | |
| 68 | 67 | pool: make(chan *WebView, cfg.MaxSize), | |
| 69 | - | ctx: logging.WithComponent(ctx, "webview-pool"), | |
| 70 | 68 | injector: injector, | |
| 71 | 69 | router: router, | |
| 72 | 70 | } | |
| 73 | 71 | ||
| 72 | + | log := logging.FromContext(ctx) | |
| 73 | + | log.Debug().Msg("creating webview pool") | |
| 74 | + | ||
| 74 | 75 | return p | |
| 75 | 76 | } | |
| 76 | 77 | ||
| 77 | 78 | // Acquire gets a WebView from the pool or creates a new one. | |
| 78 | 79 | func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) { | |
| 79 | - | log := logging.FromContext(p.ctx) | |
| 80 | + | log := logging.FromContext(ctx) | |
| 80 | 81 | ||
| 81 | 82 | if p.closed.Load() { | |
| 82 | 83 | return nil, context.Canceled | |
| @@ -87,7 +88,7 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) { | |||
| 87 | 88 | case wv := <-p.pool: | |
| 88 | 89 | if wv != nil && !wv.IsDestroyed() { | |
| 89 | 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 | 92 | log.Debug().Uint64("id", uint64(wv.ID())).Msg("acquired webview from pool") | |
| 92 | 93 | return wv, nil | |
| 93 | 94 | } | |
| @@ -98,13 +99,13 @@ func (p *WebViewPool) Acquire(ctx context.Context) (*WebView, error) { | |||
| 98 | 99 | ||
| 99 | 100 | // Pool empty or pooled view was destroyed, create new | |
| 100 | 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 | - | log := logging.FromContext(p.ctx) | |
| 105 | + | func (p *WebViewPool) createWebView(ctx context.Context) (*WebView, error) { | |
| 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 | 109 | if err != nil { | |
| 109 | 110 | return nil, err | |
| 110 | 111 | } | |
| @@ -112,7 +113,7 @@ func (p *WebViewPool) createWebView() (*WebView, error) { | |||
| 112 | 113 | // Ensure WebView is visible when used | |
| 113 | 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 | 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 | 123 | // Release returns a WebView to the pool. | |
| 123 | 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 | 128 | if wv == nil || wv.IsDestroyed() || p.closed.Load() { | |
| 126 | 129 | if wv != nil && !wv.IsDestroyed() { | |
| 127 | 130 | wv.Destroy() | |
| @@ -130,7 +133,7 @@ func (p *WebViewPool) Release(wv *WebView) { | |||
| 130 | 133 | } | |
| 131 | 134 | ||
| 132 | 135 | // Reset to blank state | |
| 133 | - | _ = wv.LoadURI(p.ctx, "about:blank") | |
| 136 | + | _ = wv.LoadURI(ctx, "about:blank") | |
| 134 | 137 | ||
| 135 | 138 | // Clear callbacks | |
| 136 | 139 | wv.OnLoadChanged = nil | |
| @@ -139,8 +142,6 @@ func (p *WebViewPool) Release(wv *WebView) { | |||
| 139 | 142 | wv.OnProgressChanged = nil | |
| 140 | 143 | wv.OnClose = nil | |
| 141 | 144 | ||
| 142 | - | log := logging.FromContext(p.ctx) | |
| 143 | - | ||
| 144 | 145 | // Try to return to pool (non-blocking) | |
| 145 | 146 | select { | |
| 146 | 147 | case p.pool <- wv: | |
| @@ -154,19 +155,19 @@ func (p *WebViewPool) Release(wv *WebView) { | |||
| 154 | 155 | ||
| 155 | 156 | // Prewarm creates WebViews synchronously to populate the pool. | |
| 156 | 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 | 159 | if count <= 0 { | |
| 159 | 160 | count = p.config.PrewarmCount | |
| 160 | 161 | } | |
| 161 | 162 | if count <= 0 { | |
| 162 | 163 | return | |
| 163 | 164 | } | |
| 164 | - | p.prewarmSync(count) | |
| 165 | + | p.prewarmSync(ctx, count) | |
| 165 | 166 | } | |
| 166 | 167 | ||
| 167 | 168 | // 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) | |
| 170 | 171 | ||
| 171 | 172 | for i := 0; i < count && !p.closed.Load(); i++ { | |
| 172 | 173 | // Check if pool is already at capacity | |
| @@ -174,7 +175,7 @@ func (p *WebViewPool) prewarmSync(count int) { | |||
| 174 | 175 | break | |
| 175 | 176 | } | |
| 176 | 177 | ||
| 177 | - | wv, err := p.createWebView() | |
| 178 | + | wv, err := p.createWebView(ctx) | |
| 178 | 179 | if err != nil { | |
| 179 | 180 | log.Warn().Err(err).Msg("failed to prewarm webview") | |
| 180 | 181 | continue | |
| @@ -201,12 +202,12 @@ func (p *WebViewPool) Size() int { | |||
| 201 | 202 | } | |
| 202 | 203 | ||
| 203 | 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 | 206 | if p.closed.Swap(true) { | |
| 206 | 207 | return // Already closed | |
| 207 | 208 | } | |
| 208 | 209 | ||
| 209 | - | log := logging.FromContext(p.ctx) | |
| 210 | + | log := logging.FromContext(ctx) | |
| 210 | 211 | ||
| 211 | 212 | // Wait for any background operations | |
| 212 | 213 | p.wg.Wait() | |
| @@ -38,7 +38,6 @@ type WebViewPool struct { | |||||
| 38 | config PoolConfig | 38 | config PoolConfig | ||
| 39 | 39 | ||||
| 40 | pool chan *WebView | 40 | pool chan *WebView | ||
| 41 | - | ctx context.Context | |||
| 42 | injector *ContentInjector | 41 | injector *ContentInjector | ||
| 43 | router *MessageRouter | 42 | 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 p | 75 | 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.Canceled | 83 | 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, nil | 93 | 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 new | 100 | // 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, err | 110 | return nil, err | ||
| 110 | } | 111 | } | ||
| @@ -112,7 +113,7 @@ func (p *WebViewPool) createWebView() (*WebView, error) { | |||||
| 112 | // Ensure WebView is visible when used | 113 | // 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 state | 135 | // Reset to blank state | ||
| 133 | - | _ = wv.LoadURI(p.ctx, "about:blank") | 136 | + | _ = wv.LoadURI(ctx, "about:blank") |
| 134 | 137 | ||||
| 135 | // Clear callbacks | 138 | // Clear callbacks | ||
| 136 | wv.OnLoadChanged = nil | 139 | wv.OnLoadChanged = nil | ||
| @@ -139,8 +142,6 @@ func (p *WebViewPool) Release(wv *WebView) { | |||||
| 139 | wv.OnProgressChanged = nil | 142 | wv.OnProgressChanged = nil | ||
| 140 | wv.OnClose = nil | 143 | 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.PrewarmCount | 160 | count = p.config.PrewarmCount | ||
| 160 | } | 161 | } | ||
| 161 | if count <= 0 { | 162 | if count <= 0 { | ||
| 162 | return | 163 | 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 capacity | 173 | // Check if pool is already at capacity | ||
| @@ -174,7 +175,7 @@ func (p *WebViewPool) prewarmSync(count int) { | |||||
| 174 | break | 175 | 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 | continue | 181 | 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 closed | 207 | 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 operations | 212 | // Wait for any background operations | ||
| 212 | p.wg.Wait() | 213 | p.wg.Wait() | ||