mirror of
https://github.com/Monadical-SAS/cubbi.git
synced 2025-12-20 20:29:06 +00:00
feat(cli): more information when closing session
This commit is contained in:
@@ -161,9 +161,29 @@ def close_session(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Close a MC session or all sessions"""
|
"""Close a MC session or all sessions"""
|
||||||
if all_sessions:
|
if all_sessions:
|
||||||
with console.status("Closing all sessions..."):
|
# Get sessions first to display them
|
||||||
count, success = container_manager.close_all_sessions()
|
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:
|
if success:
|
||||||
console.print(f"[green]{count} sessions closed successfully[/green]")
|
console.print(f"[green]{count} sessions closed successfully[/green]")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
import docker
|
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 docker.errors import DockerException, ImageNotFound
|
||||||
|
|
||||||
from .models import Session, SessionStatus
|
from .models import Session, SessionStatus
|
||||||
@@ -198,12 +199,8 @@ class ContainerManager:
|
|||||||
try:
|
try:
|
||||||
sessions = self.list_sessions()
|
sessions = self.list_sessions()
|
||||||
for session in sessions:
|
for session in sessions:
|
||||||
if session.id == session_id and session.container_id:
|
if session.id == session_id:
|
||||||
container = self.client.containers.get(session.container_id)
|
return self._close_single_session(session)
|
||||||
container.stop()
|
|
||||||
container.remove()
|
|
||||||
self.config_manager.remove_session(session_id)
|
|
||||||
return True
|
|
||||||
|
|
||||||
print(f"Session '{session_id}' not found")
|
print(f"Session '{session_id}' not found")
|
||||||
return False
|
return False
|
||||||
@@ -233,8 +230,34 @@ class ContainerManager:
|
|||||||
print(f"Error connecting to session: {e}")
|
print(f"Error connecting to session: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def close_all_sessions(self) -> tuple[int, bool]:
|
def _close_single_session(self, session: Session) -> bool:
|
||||||
"""Close all MC sessions
|
"""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:
|
Returns:
|
||||||
tuple: (number of sessions closed, success)
|
tuple: (number of sessions closed, success)
|
||||||
@@ -244,19 +267,59 @@ class ContainerManager:
|
|||||||
if not sessions:
|
if not sessions:
|
||||||
return 0, True
|
return 0, True
|
||||||
|
|
||||||
count = 0
|
# No need for session status as we receive it via callback
|
||||||
for session in sessions:
|
|
||||||
if session.container_id:
|
# 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)
|
||||||
|
|
||||||
|
# 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:
|
try:
|
||||||
container = self.client.containers.get(session.container_id)
|
success = future.result()
|
||||||
container.stop()
|
if success:
|
||||||
container.remove()
|
closed_count += 1
|
||||||
self.config_manager.remove_session(session.id)
|
except Exception as e:
|
||||||
count += 1
|
|
||||||
except DockerException as e:
|
|
||||||
print(f"Error closing session {session.id}: {e}")
|
print(f"Error closing session {session.id}: {e}")
|
||||||
|
|
||||||
return count, count > 0
|
return closed_count, closed_count > 0
|
||||||
|
|
||||||
except DockerException as e:
|
except DockerException as e:
|
||||||
print(f"Error closing all sessions: {e}")
|
print(f"Error closing all sessions: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user