From ca0bc7bdc04b05c5e938bf136fbd17288de4ae30 Mon Sep 17 00:00:00 2001 From: Adam Cohen Hillel Date: Fri, 18 Apr 2025 15:11:59 +0100 Subject: [PATCH] Add check in get project to sandbox status, and start it if stopped --- backend/sandbox/api.py | 45 ++++++++++++++++++++++++++++++++++++++ backend/sandbox/sandbox.py | 4 +--- frontend/src/lib/api.ts | 27 +++++++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/backend/sandbox/api.py b/backend/sandbox/api.py index f539fb4b..de4d2e47 100644 --- a/backend/sandbox/api.py +++ b/backend/sandbox/api.py @@ -195,3 +195,48 @@ async def read_file( except Exception as e: logger.error(f"Error reading file in sandbox {sandbox_id}: {str(e)}") raise HTTPException(status_code=500, detail=str(e)) + +@router.post("/project/{project_id}/sandbox/ensure-active") +async def ensure_project_sandbox_active( + project_id: str, + user_id: str = Depends(get_current_user_id) +): + """ + Ensure that a project's sandbox is active and running. + Checks the sandbox status and starts it if it's not running. + """ + client = await db.client + + # Find the project and sandbox information + project_result = await client.table('projects').select('*').eq('project_id', project_id).execute() + + if not project_result.data or len(project_result.data) == 0: + raise HTTPException(status_code=404, detail="Project not found") + + project_data = project_result.data[0] + account_id = project_data.get('account_id') + + # Verify account membership + if account_id: + account_user_result = await client.schema('basejump').from_('account_user').select('account_role').eq('user_id', user_id).eq('account_id', account_id).execute() + if not (account_user_result.data and len(account_user_result.data) > 0): + raise HTTPException(status_code=403, detail="Not authorized to access this project") + + # Check if project has a sandbox + sandbox_id = project_data.get('sandbox', {}).get('id') + if not sandbox_id: + raise HTTPException(status_code=404, detail="No sandbox found for this project") + + try: + # Get or start sandbox instance + logger.info(f"Ensuring sandbox {sandbox_id} is active for project {project_id}") + sandbox = await get_or_start_sandbox(sandbox_id) + + return { + "status": "success", + "sandbox_id": sandbox_id, + "message": "Sandbox is active" + } + except Exception as e: + logger.error(f"Error ensuring sandbox is active for project {project_id}: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) diff --git a/backend/sandbox/sandbox.py b/backend/sandbox/sandbox.py index 9b96e66a..602e10e0 100644 --- a/backend/sandbox/sandbox.py +++ b/backend/sandbox/sandbox.py @@ -1,8 +1,6 @@ import os -import requests -from time import sleep -from daytona_sdk import Daytona, DaytonaConfig, CreateSandboxParams, SessionExecuteRequest, Sandbox +from daytona_sdk import Daytona, DaytonaConfig, CreateSandboxParams, Sandbox from daytona_api_client.models.workspace_state import WorkspaceState from dotenv import load_dotenv diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index a09c3f1f..fc654966 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -176,6 +176,33 @@ export const getProject = async (projectId: string): Promise => { .single(); if (error) throw error; + + // If project has a sandbox, ensure it's started + if (data.sandbox?.id) { + try { + const { data: { session } } = await supabase.auth.getSession(); + if (session?.access_token) { + console.log(`Ensuring sandbox is active for project ${projectId}...`); + const response = await fetch(`${API_URL}/project/${projectId}/sandbox/ensure-active`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${session.access_token}`, + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + const errorText = await response.text().catch(() => 'No error details available'); + console.warn(`Failed to ensure sandbox is active: ${response.status} ${response.statusText}`, errorText); + } else { + console.log('Sandbox activation successful'); + } + } + } catch (sandboxError) { + console.warn('Failed to ensure sandbox is active:', sandboxError); + // Non-blocking error - continue with the project data + } + } // Cache the result apiCache.setProject(projectId, data);