From f5b345739099b49eb74941c86d2bbe7dce548e7c Mon Sep 17 00:00:00 2001 From: R0m1k3 Date: Tue, 10 Mar 2026 16:25:46 +0100 Subject: [PATCH] refactor: Consolidate Flutter web and Dart server compilation into a single Docker build stage for streamlined dependency management. --- Dockerfile.fast | 45 +++++++++++++++++++ bin/api/proxy_handler.dart | 9 ++-- .../iptv/providers/xtream_provider.dart | 23 ++++++++-- update_fast.ps1 | 30 +++++++++++++ 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 Dockerfile.fast create mode 100644 update_fast.ps1 diff --git a/Dockerfile.fast b/Dockerfile.fast new file mode 100644 index 0000000..86d9705 --- /dev/null +++ b/Dockerfile.fast @@ -0,0 +1,45 @@ +# Dockerfile optimisé pour mises à jour rapides (Fast-Path) +# Ce Dockerfile assume que les fichiers Flutter Web ont déjà été compilés en local +# dans le dossier `build/web`. + +FROM debian:stable-slim + +# Éviter les prompts à l'installation +ENV DEBIAN_FRONTEND=noninteractive + +# Installation des dépendances minimales (Dart + FFmpeg) +RUN apt-get update && apt-get install -y --no-install-recommends \ + wget \ + ca-certificates \ + unzip \ + ffmpeg \ + && rm -rf /var/lib/apt/lists/* + +# Installation de Dart SDK (version spécifique pour compatibilité) +RUN wget https://storage.googleapis.com/dart-archive/channels/stable/release/3.3.0/sdk/dartsdk-linux-x64-release.zip -O /tmp/dart-sdk.zip && \ + unzip /tmp/dart-sdk.zip -d /usr/lib && \ + rm /tmp/dart-sdk.zip + +ENV PATH="/usr/lib/dart-sdk/bin:${PATH}" + +# Création de l'utilisateur non-root +RUN useradd -m xtremuser +WORKDIR /app + +# Création des dossiers de données avec permissions +RUN mkdir -p /app/data/logs /app/data/tmp /app/web && \ + chown -R xtremuser:xtremuser /app + +# Copie des fichiers pré-compilés du serveur (doit être compilé en local si possible, sinon ici) +COPY --chown=xtremuser:xtremuser bin/ /app/bin/ +RUN cd bin && dart pub get + +# Copie des fichiers pré-compilés du frontend (build/web doit exister en local) +COPY --chown=xtremuser:xtremuser build/web/ /app/web/ + +USER xtremuser +EXPOSE 8089 + +# Commande de lancement (compilation JIT du serveur pour rapidité de build, ou EXE si déjà fait) +# Pour une rapidité maximale de "build", on lance le script dart directement car la compilation EXE prend du temps. +CMD ["dart", "bin/server.dart", "--port", "8089", "--path", "/app/web"] diff --git a/bin/api/proxy_handler.dart b/bin/api/proxy_handler.dart index 720a889..b03fb06 100644 --- a/bin/api/proxy_handler.dart +++ b/bin/api/proxy_handler.dart @@ -10,6 +10,7 @@ import '../database/database.dart'; class ProxyHandler { final Future Function(Request) _getPlaylist; final AppDatabase _db; + final http.Client _client = http.Client(); static const _allowedHeaders = [ 'content-type', @@ -122,7 +123,6 @@ class ProxyHandler { 'User-Agent': 'VLC/3.0.18 LibVLC/3.0.18', 'Accept': '*/*', 'Accept-Encoding': 'identity', - 'Connection': 'close', }; // Forward Range header if present @@ -130,7 +130,6 @@ class ProxyHandler { proxyHeaders['range'] = request.headers['range']!; } - final client = http.Client(); try { print('[Proxy] Forwarding to: $targetUrl'); final proxyRequest = http.Request(request.method, targetUrl); @@ -142,7 +141,10 @@ class ProxyHandler { proxyRequest.bodyBytes = bodyBytes.expand((i) => i).toList(); } - final response = await client.send(proxyRequest); + // Added 90s timeout to allow frontend (60s) to time out gracefully first + final response = await _client + .send(proxyRequest) + .timeout(const Duration(seconds: 90)); // Build response headers from source response final responseHeaders = { @@ -177,7 +179,6 @@ class ProxyHandler { headers: responseHeaders, ); } catch (e) { - client.close(); rethrow; } } catch (e) { diff --git a/lib/features/iptv/providers/xtream_provider.dart b/lib/features/iptv/providers/xtream_provider.dart index f21d612..b07ec9a 100644 --- a/lib/features/iptv/providers/xtream_provider.dart +++ b/lib/features/iptv/providers/xtream_provider.dart @@ -10,20 +10,35 @@ import 'settings_provider.dart'; final xtreamServiceProvider = Provider.family((ref, playlist) { final service = XtreamService(); - final settings = ref.watch(iptvSettingsProvider); + final settings = ref.read(iptvSettingsProvider); service.setBackendUrl(settings.backendUrl); service.updateTimeouts(settings.timeoutSeconds); service.setPlaylist(playlist); - ref.onDispose(() => service.dispose()); + + // Update instance without rebuilding the provider to keep connectivity active + ref.listen(iptvSettingsProvider, (previous, next) { + service.setBackendUrl(next.backendUrl); + service.updateTimeouts(next.timeoutSeconds); + }); + + // ref.onDispose(() => service.dispose()); // Removed to prevent premature Dio destruction return service; }); /// Singleton Xtream service provider (legacy, for activeXtreamServiceProvider) final _singletonXtreamServiceProvider = Provider((ref) { final service = XtreamService(); - final settings = ref.watch(iptvSettingsProvider); + final settings = ref.read(iptvSettingsProvider); service.setBackendUrl(settings.backendUrl); - ref.onDispose(() => service.dispose()); + service.updateTimeouts(settings.timeoutSeconds); + + // Update instance without rebuilding the provider + ref.listen(iptvSettingsProvider, (previous, next) { + service.setBackendUrl(next.backendUrl); + service.updateTimeouts(next.timeoutSeconds); + }); + + // ref.onDispose(() => service.dispose()); // Removed to prevent premature Dio destruction return service; }); diff --git a/update_fast.ps1 b/update_fast.ps1 new file mode 100644 index 0000000..a755349 --- /dev/null +++ b/update_fast.ps1 @@ -0,0 +1,30 @@ +# Script de mise à jour rapide pour XtremFlow +# Michael, lancez ce script pour mettre à jour l'app en < 60s. + +Write-Host "🚀 Lancement du workflow Fast-Path BMAD..." -ForegroundColor Cyan + +# 1. Compilation locale du frontend (utilise le cache local de votre machine) +Write-Host "📦 Compilation locale du frontend Flutter..." -ForegroundColor Yellow +flutter build web --release --base-href="/" --no-tree-shake-icons + +if ($LASTEXITCODE -ne 0) { + Write-Host "❌ Erreur lors du build Flutter. Abandon." -ForegroundColor Red + exit 1 +} + +# 2. Build de l'image Docker légère (pas de compilation interne) +Write-Host "🏗️ Construction de l'image Docker légère..." -ForegroundColor Yellow +docker build -f Dockerfile.fast -t xtremflow-fast . + +if ($LASTEXITCODE -ne 0) { + Write-Host "❌ Erreur lors du build Docker. Abandon." -ForegroundColor Red + exit 1 +} + +# 3. Redémarrage de la stack avec l'image rapide +Write-Host "🔄 Redémarrage des services..." -ForegroundColor Yellow +docker compose down +docker compose up -d + +Write-Host "✅ Mise à jour terminée en un temps record !" -ForegroundColor Green +Write-Host "🌐 Accédez à l'app sur http://localhost:8089" -ForegroundColor Cyan