fix: try to fix error on update on computer switch off

This commit is contained in:
2026-05-19 08:11:28 +02:00
parent 4ba70cefc6
commit 8d0d9835be
7 changed files with 161 additions and 20 deletions

View File

@ -72,30 +72,26 @@ class Daemon:
existing.add(pkg.name)
self._save()
# Pré-télécharger tous les paquets reportés pendant que le réseau est disponible
safe_names = [p.name for p in safe]
pending_names = [p["name"] for p in self._state["pending_restart"]]
if pending_names:
logger.info(f"Pré-téléchargement des paquets reportés : {', '.join(pending_names)}")
ok = await asyncio.to_thread(download_packages, pending_names)
if not ok:
logger.warning("Pré-téléchargement partiel — une nouvelle tentative aura lieu au prochain cycle")
# Télécharger safe + reportés en une seule transaction pour que pacman
# puisse résoudre toutes les dépendances inter-paquets correctement.
all_names = list(dict.fromkeys(safe_names + pending_names))
self._set_status("downloading")
logger.info(f"Téléchargement ({len(all_names)} paquets) : {', '.join(all_names)}")
ok = await asyncio.to_thread(download_packages, all_names)
if not ok:
self._add_error("Échec du téléchargement des paquets")
self._set_status("error")
return
if not safe:
logger.info("Aucun paquet à installer immédiatement")
self._set_status("idle")
return
# Synchroniser la DB et télécharger
self._set_status("downloading")
safe_names = [p.name for p in safe]
logger.info(f"Téléchargement : {', '.join(safe_names)}")
ok = await asyncio.to_thread(download_packages, safe_names)
if not ok:
self._add_error("Échec du téléchargement des paquets")
self._set_status("error")
return
# Installer les paquets sûrs
self._set_status("installing")
logger.info(f"Installation : {', '.join(safe_names)}")
@ -129,6 +125,51 @@ class Daemon:
self._add_error(str(e))
self._set_status("error")
async def install_pending_cycle(self):
if self._state["status"] not in ("idle", "error"):
logger.info("Une opération est déjà en cours, installation ignorée")
return
pending = self._state.get("pending_restart", [])
if not pending:
logger.info("Aucun paquet en attente à installer")
return
if is_pacman_locked():
logger.info("pacman est verrouillé, impossible d'installer maintenant")
self._add_error("pacman est verrouillé, réessayez dans quelques instants")
return
names = [p["name"] for p in pending]
try:
self._set_status("installing")
logger.info(f"Installation manuelle : {', '.join(names)}")
result = await asyncio.to_thread(install_packages, names)
if result.success:
logger.info("Installation manuelle réussie")
now = datetime.now().isoformat()
for pkg in pending:
self._state["installed_history"].append({**pkg, "installed_at": now})
self._state["installed_history"] = self._state["installed_history"][-200:]
self._state["pending_restart"] = []
installed_set = set(names)
self._state["available_updates"] = [
u for u in self._state["available_updates"]
if u["name"] not in installed_set
]
else:
logger.error(f"Installation manuelle échouée : {result.error}")
self._add_error(f"Échec de l'installation : {result.error}")
self._set_status("idle")
except Exception as e:
logger.exception(f"Erreur lors de l'installation manuelle : {e}")
self._add_error(str(e))
self._set_status("error")
def _add_error(self, message: str):
self._state["errors"].append({
"time": datetime.now().isoformat(),
@ -146,6 +187,9 @@ class Daemon:
if action == "check_now":
asyncio.create_task(self.update_cycle())
response = {"status": "ok", "message": "Vérification lancée"}
elif action == "install_pending":
asyncio.create_task(self.install_pending_cycle())
response = {"status": "ok", "message": "Installation lancée"}
elif action == "get_state":
response = {"status": "ok", "state": self._state}
else: