feat(cli): more information when closing session

This commit is contained in:
2025-03-10 23:07:32 -06:00
parent e6e3c207bc
commit 08ba1ab2da
2 changed files with 104 additions and 21 deletions

View File

@@ -161,9 +161,29 @@ def close_session(
) -> None:
"""Close a MC session or all sessions"""
if all_sessions:
with console.status("Closing all sessions..."):
count, success = container_manager.close_all_sessions()
# Get sessions first to display them
sessions = container_manager.list_sessions()
if not sessions:
console.print("No active sessions to close")
return
console.print(f"Closing {len(sessions)} sessions...")
# Simple progress function that prints a line when a session is closed
def update_progress(session_id, status, message):
if status == "completed":
console.print(
f"[green]Session {session_id} closed successfully[/green]"
)
elif status == "failed":
console.print(
f"[red]Failed to close session {session_id}: {message}[/red]"
)
# Start closing sessions with progress updates
count, success = container_manager.close_all_sessions(update_progress)
# Final result
if success:
console.print(f"[green]{count} sessions closed successfully[/green]")
else:

View File

@@ -2,7 +2,8 @@ import os
import sys
import uuid
import docker
from typing import Dict, List, Optional
import concurrent.futures
from typing import Dict, List, Optional, Tuple
from docker.errors import DockerException, ImageNotFound
from .models import Session, SessionStatus
@@ -198,12 +199,8 @@ class ContainerManager:
try:
sessions = self.list_sessions()
for session in sessions:
if session.id == session_id and session.container_id:
container = self.client.containers.get(session.container_id)
container.stop()
container.remove()
self.config_manager.remove_session(session_id)
return True
if session.id == session_id:
return self._close_single_session(session)
print(f"Session '{session_id}' not found")
return False
@@ -233,8 +230,34 @@ class ContainerManager:
print(f"Error connecting to session: {e}")
return False
def close_all_sessions(self) -> tuple[int, bool]:
"""Close all MC sessions
def _close_single_session(self, session: Session) -> bool:
"""Close a single session (helper for parallel processing)
Args:
session: The session to close
Returns:
bool: Whether the session was successfully closed
"""
if not session.container_id:
return False
try:
container = self.client.containers.get(session.container_id)
container.stop()
container.remove()
self.config_manager.remove_session(session.id)
return True
except DockerException as e:
print(f"Error closing session {session.id}: {e}")
return False
def close_all_sessions(self, progress_callback=None) -> Tuple[int, bool]:
"""Close all MC sessions with parallel processing and progress reporting
Args:
progress_callback: Optional callback function to report progress
The callback should accept (session_id, status, message)
Returns:
tuple: (number of sessions closed, success)
@@ -244,19 +267,59 @@ class ContainerManager:
if not sessions:
return 0, True
count = 0
for session in sessions:
if session.container_id:
# No need for session status as we receive it via callback
# Define a wrapper to track progress
def close_with_progress(session):
if not session.container_id:
return False
try:
container = self.client.containers.get(session.container_id)
# Stop and remove container
container.stop()
container.remove()
# Remove from config
self.config_manager.remove_session(session.id)
count += 1
# Notify about completion
if progress_callback:
progress_callback(
session.id,
"completed",
f"{session.name} closed successfully",
)
return True
except DockerException as e:
error_msg = f"Error: {str(e)}"
if progress_callback:
progress_callback(session.id, "failed", error_msg)
print(f"Error closing session {session.id}: {e}")
return False
# Use ThreadPoolExecutor to close sessions in parallel
with concurrent.futures.ThreadPoolExecutor(
max_workers=min(10, len(sessions))
) as executor:
# Submit all session closing tasks
future_to_session = {
executor.submit(close_with_progress, session): session
for session in sessions
}
# Collect results
closed_count = 0
for future in concurrent.futures.as_completed(future_to_session):
session = future_to_session[future]
try:
success = future.result()
if success:
closed_count += 1
except Exception as e:
print(f"Error closing session {session.id}: {e}")
return count, count > 0
return closed_count, closed_count > 0
except DockerException as e:
print(f"Error closing all sessions: {e}")