good version for 算法注册
This commit is contained in:
@@ -14,6 +14,7 @@ from app.schemas.user import UserResponse
|
||||
from app.services.project_analyzer import ProjectAnalyzer
|
||||
from app.services.service_generator import ServiceGenerator
|
||||
from app.services.service_orchestrator import ServiceOrchestrator
|
||||
from app.gitea.service import gitea_service
|
||||
|
||||
router = APIRouter(prefix="/services", tags=["services"])
|
||||
|
||||
@@ -23,6 +24,9 @@ class RegisterServiceRequest(BaseModel):
|
||||
repository_id: str
|
||||
name: str
|
||||
version: str = "1.0.0"
|
||||
description: Optional[str] = ""
|
||||
tech_category: str = "computer_vision"
|
||||
output_type: str = "image"
|
||||
service_type: str = "http"
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 8000
|
||||
@@ -154,31 +158,24 @@ async def register_service(
|
||||
# 记录仓库信息
|
||||
print(f"仓库信息: {repo.name}, {repo.description}, {repo.repo_url}")
|
||||
|
||||
# 2. 分析项目
|
||||
repo_path = f"/tmp/repository_{request.repository_id}"
|
||||
# 注意:在实际实现中,应该从算法仓库中获取项目文件
|
||||
# 这里简化处理,创建一个模拟的项目结构
|
||||
os.makedirs(repo_path, exist_ok=True)
|
||||
# 2. 从Gitea仓库克隆代码到本地
|
||||
repo_path = f"/tmp/algorithms/{request.repository_id}"
|
||||
|
||||
# 创建模拟的算法文件
|
||||
with open(os.path.join(repo_path, "algorithm.py"), "w") as f:
|
||||
f.write("""
|
||||
def predict(data):
|
||||
return {"result": "Prediction result", "input": data}
|
||||
|
||||
def run(data):
|
||||
return {"result": "Run result", "input": data}
|
||||
|
||||
def main(data):
|
||||
return {"result": "Main result", "input": data}
|
||||
""")
|
||||
# 使用Gitea服务克隆仓库
|
||||
clone_success = gitea_service.clone_repository(repo.repo_url, request.repository_id, repo.branch or "main")
|
||||
if not clone_success:
|
||||
raise HTTPException(status_code=400, detail=f"克隆仓库失败: {repo.repo_url}")
|
||||
|
||||
# 分析项目
|
||||
print(f"仓库克隆成功: {repo_path}")
|
||||
|
||||
# 3. 分析项目
|
||||
project_info = project_analyzer.analyze_project(repo_path)
|
||||
if not project_info["success"]:
|
||||
raise HTTPException(status_code=400, detail=f"项目分析失败: {project_info['error']}")
|
||||
|
||||
# 3. 生成服务包装器
|
||||
print(f"项目分析成功: {project_info}")
|
||||
|
||||
# 4. 生成服务包装器
|
||||
service_config = {
|
||||
"name": request.name,
|
||||
"version": request.version,
|
||||
@@ -194,24 +191,31 @@ def main(data):
|
||||
if not generate_result["success"]:
|
||||
raise HTTPException(status_code=400, detail=f"服务生成失败: {generate_result['error']}")
|
||||
|
||||
# 4. 部署服务
|
||||
print(f"服务生成成功: {generate_result}")
|
||||
|
||||
# 5. 部署服务
|
||||
service_id = str(uuid.uuid4())
|
||||
deploy_result = service_orchestrator.deploy_service(service_id, service_config, project_info)
|
||||
deploy_result = service_orchestrator.deploy_service(service_id, service_config, project_info, repo_path)
|
||||
if not deploy_result["success"]:
|
||||
raise HTTPException(status_code=400, detail=f"服务部署失败: {deploy_result['error']}")
|
||||
|
||||
# 5. 保存服务信息到数据库
|
||||
print(f"服务部署成功: {deploy_result}")
|
||||
|
||||
# 6. 保存服务信息到数据库
|
||||
new_service = AlgorithmService(
|
||||
id=str(uuid.uuid4()),
|
||||
service_id=service_id,
|
||||
name=request.name,
|
||||
algorithm_name=repo.name, # 使用仓库名称作为算法名称
|
||||
version=request.version,
|
||||
tech_category=request.tech_category,
|
||||
output_type=request.output_type,
|
||||
host=request.host,
|
||||
port=request.port,
|
||||
api_url=deploy_result["api_url"],
|
||||
status=deploy_result["status"],
|
||||
config={
|
||||
"repository_id": request.repository_id, # 保存仓库ID
|
||||
"service_type": request.service_type,
|
||||
"timeout": request.timeout,
|
||||
"health_check_path": request.health_check_path,
|
||||
@@ -352,8 +356,64 @@ async def start_service(
|
||||
|
||||
# 启动服务
|
||||
start_result = service_orchestrator.start_service(service_id, container_id)
|
||||
|
||||
# 如果启动失败,尝试从数据库重新注册服务
|
||||
if not start_result["success"]:
|
||||
raise HTTPException(status_code=400, detail=f"服务启动失败: {start_result['error']}")
|
||||
print(f"服务启动失败: {start_result['error']},尝试从数据库重新注册服务")
|
||||
|
||||
# 获取仓库信息
|
||||
repository_id = service.config.get("repository_id")
|
||||
if not repository_id:
|
||||
raise HTTPException(status_code=400, detail="Repository ID not found in service config")
|
||||
|
||||
repository = db.query(AlgorithmRepository).filter(AlgorithmRepository.id == repository_id).first()
|
||||
if not repository:
|
||||
raise HTTPException(status_code=404, detail="Repository not found")
|
||||
|
||||
# 从Gitea克隆仓库
|
||||
clone_success = gitea_service.clone_repository(
|
||||
repository.repo_url,
|
||||
service_id,
|
||||
repository.branch or "main"
|
||||
)
|
||||
if not clone_success:
|
||||
raise HTTPException(status_code=400, detail="Failed to clone repository")
|
||||
|
||||
# 仓库路径
|
||||
repo_path = f"/tmp/algorithms/{service_id}"
|
||||
|
||||
# 分析项目
|
||||
project_info = project_analyzer.analyze_project(repo_path)
|
||||
if not project_info:
|
||||
raise HTTPException(status_code=400, detail="Failed to analyze project")
|
||||
|
||||
# 生成服务
|
||||
service_config = {
|
||||
"name": service.name,
|
||||
"version": service.version,
|
||||
"host": service.host,
|
||||
"port": service.port,
|
||||
"timeout": service.config.get("timeout", 30),
|
||||
"health_check_path": service.config.get("health_check_path", "/health"),
|
||||
"environment": service.config.get("environment", {})
|
||||
}
|
||||
|
||||
# 部署服务
|
||||
deploy_result = service_orchestrator.deploy_service(service_id, project_info, service_config, repo_path)
|
||||
if not deploy_result["success"]:
|
||||
raise HTTPException(status_code=400, detail=f"服务部署失败: {deploy_result['error']}")
|
||||
|
||||
# 更新服务配置
|
||||
service.config["container_id"] = deploy_result["container_id"]
|
||||
service.api_url = deploy_result["api_url"]
|
||||
db.commit()
|
||||
|
||||
start_result = {
|
||||
"success": True,
|
||||
"service_id": service_id,
|
||||
"status": "running",
|
||||
"error": None
|
||||
}
|
||||
|
||||
# 更新服务状态
|
||||
service.status = start_result["status"]
|
||||
@@ -1065,3 +1125,108 @@ async def batch_delete_services(
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
class ServiceCallRequest(BaseModel):
|
||||
"""服务调用请求"""
|
||||
service_id: str
|
||||
payload: Dict[str, Any]
|
||||
|
||||
|
||||
class ServiceCallResponse(BaseModel):
|
||||
"""服务调用响应"""
|
||||
success: bool
|
||||
result: Dict[str, Any]
|
||||
service_id: str
|
||||
execution_time: float
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
@router.post("/call")
|
||||
async def call_service(
|
||||
request: ServiceCallRequest,
|
||||
current_user: UserResponse = Depends(get_current_active_user)
|
||||
):
|
||||
"""直接调用注册的服务"""
|
||||
import time
|
||||
import httpx
|
||||
|
||||
# 创建数据库会话
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# 查询服务
|
||||
service = db.query(AlgorithmService).filter(
|
||||
AlgorithmService.service_id == request.service_id
|
||||
).first()
|
||||
|
||||
if not service:
|
||||
raise HTTPException(status_code=404, detail="服务不存在")
|
||||
|
||||
# 检查服务状态
|
||||
if service.status != "running":
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail=f"服务未运行,当前状态: {service.status}"
|
||||
)
|
||||
|
||||
# 调用服务
|
||||
start_time = time.time()
|
||||
|
||||
try:
|
||||
# 构建服务URL
|
||||
service_url = service.api_url
|
||||
|
||||
# 如果URL没有路径,添加默认路径
|
||||
if not service_url.endswith("/"):
|
||||
service_url += "/"
|
||||
|
||||
# 添加调用端点
|
||||
call_url = f"{service_url}predict"
|
||||
|
||||
# 使用httpx调用服务
|
||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||
response = await client.post(
|
||||
call_url,
|
||||
json=request.payload,
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
|
||||
execution_time = time.time() - start_time
|
||||
|
||||
if response.status_code == 200:
|
||||
return ServiceCallResponse(
|
||||
success=True,
|
||||
result=response.json(),
|
||||
service_id=request.service_id,
|
||||
execution_time=execution_time
|
||||
)
|
||||
else:
|
||||
return ServiceCallResponse(
|
||||
success=False,
|
||||
result={},
|
||||
service_id=request.service_id,
|
||||
execution_time=execution_time,
|
||||
error=f"服务返回错误: HTTP {response.status_code} - {response.text}"
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
execution_time = time.time() - start_time
|
||||
return ServiceCallResponse(
|
||||
success=False,
|
||||
result={},
|
||||
service_id=request.service_id,
|
||||
execution_time=execution_time,
|
||||
error=f"无法连接到服务: {str(e)}"
|
||||
)
|
||||
except Exception as e:
|
||||
execution_time = time.time() - start_time
|
||||
return ServiceCallResponse(
|
||||
success=False,
|
||||
result={},
|
||||
service_id=request.service_id,
|
||||
execution_time=execution_time,
|
||||
error=f"服务调用异常: {str(e)}"
|
||||
)
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
Reference in New Issue
Block a user