using Microsoft.Playwright; namespace PageFetcherApi.Services; /// /// Singleton hosted service that owns the Playwright Chromium browser process for the lifetime of the application. /// Launches the browser once at startup and exposes it for injection into . /// public sealed class PlaywrightBrowserService : IHostedService, IAsyncDisposable { private IPlaywright? _playwright; private IBrowser? _browser; private readonly ILogger _logger; public PlaywrightBrowserService(ILogger logger) { _logger = logger; } /// The running Chromium browser instance. Available after completes. public IBrowser Browser => _browser ?? throw new InvalidOperationException("Browser has not been started yet."); /// public async Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Launching Playwright Chromium browser..."); _playwright = await Playwright.CreateAsync(); _browser = await _playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true, Args = ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"] }); _logger.LogInformation("Playwright Chromium browser launched successfully."); } /// public async Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Closing Playwright Chromium browser..."); if (_browser is not null) await _browser.CloseAsync(); } /// public async ValueTask DisposeAsync() { if (_browser is not null) await _browser.DisposeAsync(); _playwright?.Dispose(); } }