désactivation async

This commit is contained in:
2025-05-26 00:31:51 +02:00
parent f442e334d0
commit 01d598684c
3 changed files with 70 additions and 70 deletions

View File

@@ -1,5 +1,3 @@
import threading
from PySide6.QtCore import QObject, Signal, QTimer, QUrl, Slot, QThread
from PySide6.QtNetwork import QNetworkCookie, QNetworkAccessManager, QNetworkRequest, QNetworkReply, QNetworkCookieJar
@@ -36,7 +34,6 @@ class DownloadManager(QObject):
self.files: dict[str, FileType] = self.conf.get_value("files", {})
self.tasks: dict[FileType, DownloaderWorker] = {}
self.task_stats: dict[str, FileStatsType] = {}
self.waiter = threading.Event()
self.cookies = {}
# slots
@@ -56,21 +53,25 @@ class DownloadManager(QObject):
self.status = {}
self.update_status()
def loop_queue(self):
self.logger.info("Démarrage de la boucle de téléchargement")
while not self.stop:
available_worker = next((worker for worker in self.worker_pool if worker.available), None)
file = next((file for file in self.files.values() if not file.downloaded and file not in self.tasks), None)
# wait if pause is true
if not available_worker or not file or self.pause:
self.logger.info("loop queue paused, waiting for tasks to finish...")
self.waiter.clear()
self.waiter.wait()
self.logger.info("loop queue resumed")
else:
self.logger.info(f"Assignation du fichier {file.id} à un worker disponible")
self.tasks[file] = available_worker
available_worker.start_download(file)
self.queue_timer = QTimer(self)
self.queue_timer.timeout.connect(self.process_queue)
self.queue_timer.start(1)
def process_queue(self):
if self.pause:
return
available_worker = next((worker for worker in self.worker_pool if worker.available), None)
file = next((file for file in self.files.values() if not file.downloaded and file not in self.tasks), None)
if available_worker and file:
self.logger.info(f"Assignation du fichier {file.id} à un worker disponible")
self.tasks[file] = available_worker
available_worker.start_download(file)
else:
self.queue_timer.stop()
if all(file.downloaded for file in self.files.values()):
self.logger.info("Tous les fichiers ont été téléchargés")
self.set_pause(True)
self.logger.info("Arrêt de la boucle de téléchargement")
@@ -82,11 +83,11 @@ class DownloadManager(QObject):
self.logger.info(f"État de pause modifié à: {value}")
if self.pause:
self.logger.info("Arrêt de tous les téléchargements actifs")
for worker in self.tasks.values():
for worker in self.tasks.copy().values():
worker.stop_download()
else:
self.logger.info("Reprise des téléchargements")
self.waiter.set()
self.queue_timer.start(1)
QTimer.singleShot(100, self.update_status)
def task_ended(self, file):
@@ -99,7 +100,7 @@ class DownloadManager(QObject):
self.task_stats.pop(file.id)
self.logger.debug("Notification du waiter pour traiter le prochain fichier")
self.waiter.set()
self.queue_timer.start(1)
self.files_updated.emit(self.files)
@@ -151,6 +152,7 @@ class DownloadManager(QObject):
"downloader_stats": {key: dl_stat.to_dict() for key, dl_stat in self.task_stats.items()}
}
if self.status != new_status:
print(new_status["downloader_stats"])
self.status = new_status
self.status_updated.emit(self.status)
self.logger.debug(f"Mise à jour du statut: {len(self.files)} fichiers, {new_status['downloaded_files']} téléchargés, Vitesse: {new_status['speed']/1024:.2f} Ko/s")
@@ -184,12 +186,13 @@ class DownloaderWorker(QObject):
self.logger = logging.getLogger('DownloaderWorker')
self.logger.info("Initialisation d'un nouveau worker de téléchargement")
self.dl_thread = QThread()
self.dl_thread.start()
self.dl_thread = QThread(self)
self.manager = QNetworkAccessManager(self)
self.manager.moveToThread(self.dl_thread)
if not self.manager.cookieJar():
self.manager.setCookieJar(QNetworkCookieJar())
# self.manager.moveToThread(self.dl_thread)
self.manager.finished.connect(self._on_finished)
self.available = True
@@ -198,8 +201,10 @@ class DownloaderWorker(QObject):
self.file: Optional[FileType] = None
self.stats: Optional[FileStatsType] = None
self.last_update_time = time.monotonic()
self.last_downloaded_size = 0
self.last_update_time = 0
self.accumulated_bytes = 0
self.dl_thread.start()
self.logger.debug("Worker de téléchargement initialisé et prêt")
@Slot(FileType)
@@ -214,6 +219,7 @@ class DownloaderWorker(QObject):
# construction des stats + vérification si le téléchargement est déjà terminé
self.file = file
self.stats = FileStatsType()
self.stats.total_size = file.total_size
self.stats.downloaded_size = file.size_downloaded
if self.stats.downloaded_size >= file.total_size:
self.logger.info(f"Le fichier {file.id} est déjà téléchargé")
@@ -243,29 +249,35 @@ class DownloaderWorker(QObject):
self.logger.debug(f"Fichier ouvert en mode {mode}: {file.target}")
self.last_update_time = time.monotonic()
self.last_downloaded_size = self.stats.downloaded_size
self.accumulated_bytes = 0
def _on_data_ready(self):
chunk = self.reply.readAll()
self.file_io.write(chunk.data())
chunk_size = 0
while self.reply.bytesAvailable():
chunk = self.reply.read(64 * 1024)
self.file_io.write(chunk.data())
chunk_size += chunk.size()
# stats calculation
chunk_size = chunk.size()
self.stats.downloaded_size += chunk_size
current_time = time.monotonic()
elapsed_time = max(current_time - self.last_update_time, 0.001)
current_speed = chunk_size / elapsed_time
if self.file.speed > 0:
self.file.speed = round(0.7 * current_speed + 0.3 * self.file.speed)
else:
self.file.speed = round(current_speed)
self.accumulated_bytes += chunk_size
now = time.monotonic()
elapsed = now - self.last_update_time
self.last_update_time = current_time
self.last_downloaded_size = chunk_size
self.logger.debug(f"Données reçues: {chunk_size} octets, vitesse: {self.file.speed/1024:.2f} Ko/s")
if elapsed >= 1.0:
# EMA lissage court terme (optionnel : 0.7 nouveau / 0.3 ancien)
new_speed = self.accumulated_bytes / elapsed
if self.stats.speed > 0:
self.stats.speed = round(0.7 * new_speed + 0.3 * self.stats.speed)
else:
self.stats.speed = round(new_speed)
self.accumulated_bytes = 0
self.last_update_time = now
# self.logger.info(f"Données reçues: {chunk_size} octets, vitesse: {self.stats.speed/1024:.2f} Ko/s")
def _on_progress(self, bytes_received, bytes_total):
self.logger.debug(f"Progression du téléchargement pour {self.file.id}: {bytes_received}/{bytes_total} octets ({(bytes_received/max(bytes_total, 1))*100:.1f}%)")
pass
# self.logger.debug(f"Progression du téléchargement pour {self.file.id}: {bytes_received}/{bytes_total} octets ({(bytes_received/max(bytes_total, 1))*100:.1f}%)")
def _on_finished(self, reply: QNetworkReply):
if not self.file:
@@ -280,8 +292,9 @@ class DownloaderWorker(QObject):
self.logger.error(f"Échec du téléchargement pour {self.file.id}: {error_msg}")
self.file.error = error_msg
self.clear()
self.download_manager.task_ended(self.file)
self.clear()
def stop_download(self):
if self.file:
@@ -301,17 +314,18 @@ class DownloaderWorker(QObject):
if not self.reply.isFinished():
self.logger.debug("Annulation de la requête réseau")
self.reply.abort()
self.reply.deleteLater()
self.reply = None
if self.reply:
self.reply.deleteLater()
self.reply = None
self.logger.debug("Requête réseau nettoyée")
if self.stats:
self.stats = None
self.logger.debug("Statistiques réinitialisées")
if self.file:
self.file = None
self.logger.debug("Référence au fichier supprimée")
# if self.stats:
# self.stats = None
# self.logger.debug("Statistiques réinitialisées")
#
# if self.file:
# self.file = None
# self.logger.debug("Référence au fichier supprimée")
self.available = True
self.logger.debug("Worker marqué comme disponible")
@@ -330,9 +344,8 @@ class DownloaderWorker(QObject):
self.reply.abort()
self.reply.deleteLater()
self.manager.deleteLater()
self.logger.debug("Arrêt du thread de téléchargement")
self.dl_thread.quit()
if not self.dl_thread.wait(3000):
self.logger.warning("Le thread ne s'est pas arrêté proprement, terminaison forcée")
self.dl_thread.terminate()
self.dl_thread.wait()
self.logger.debug("Arrêt du thread de téléchargement")
self.logger.info("Worker fermé")

View File

@@ -20,7 +20,7 @@ def configure_logging(debug_mode=False):
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
root.addHandler(handler)

View File

@@ -46,18 +46,8 @@ class MainWindow(QMainWindow):
self.site_window.on_cookie_added.connect(self.download_manager.add_cookie)
self.logger.debug("Signaux connectés")
# initialisation du gestionnaire de téléchargement
self.dm_loop = None
QTimer.singleShot(0, self.setup_tasks)
self.logger.info("Fenêtre principale initialisée avec succès")
def setup_tasks(self):
# Lancer les tâches une fois que l'application est prête
self.logger.debug("Configuration des tâches")
self.dm_loop = threading.Thread(target=self.download_manager.loop_queue, daemon=True)
self.dm_loop.start()
self.logger.debug("File d'attente de téléchargement démarrée")
def handle_files(self, file_paths):
"""
@@ -95,10 +85,7 @@ class MainWindow(QMainWindow):
def closeEvent(self, event, /):
self.download_manager.pause = True
self.download_manager.stop = True
self.download_manager.waiter.set()
self.download_manager.close_thread_workers()
self.dm_loop.join(timeout=1)
event.accept()