feat: 프로젝트 기본 구조 구축
This commit is contained in:
@@ -6,11 +6,15 @@ from django.utils import timezone
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
import requests
|
||||
import logging
|
||||
|
||||
from .models import QuantStrategy, StrategyVersion, StrategyExecution
|
||||
from .base import StrategyRegistry
|
||||
from . import implementations # 구현체들을 로드하여 레지스트리에 등록
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def list_strategies(request):
|
||||
@@ -55,6 +59,7 @@ def execute_strategy(request):
|
||||
strategy_name = data.get('strategy_name')
|
||||
version = data.get('version')
|
||||
execution_parameters = data.get('parameters', {})
|
||||
callback_url = data.get('callback_url')
|
||||
|
||||
if not strategy_name:
|
||||
return JsonResponse({
|
||||
@@ -79,7 +84,8 @@ def execute_strategy(request):
|
||||
execution = StrategyExecution.objects.create(
|
||||
strategy_version=strategy_version,
|
||||
execution_parameters=execution_parameters,
|
||||
status='pending'
|
||||
status='pending',
|
||||
callback_url=callback_url
|
||||
)
|
||||
|
||||
def run_strategy():
|
||||
@@ -108,13 +114,19 @@ def execute_strategy(request):
|
||||
execution.completed_at = timezone.now()
|
||||
execution.save()
|
||||
|
||||
finally:
|
||||
# 콜백 URL이 있으면 결과 전송
|
||||
if execution.callback_url:
|
||||
send_callback(execution)
|
||||
|
||||
thread = threading.Thread(target=run_strategy)
|
||||
thread.start()
|
||||
|
||||
return JsonResponse({
|
||||
'execution_id': execution.id,
|
||||
'status': 'pending',
|
||||
'message': 'Strategy execution started'
|
||||
'message': 'Strategy execution started',
|
||||
'callback_url': callback_url
|
||||
})
|
||||
|
||||
except json.JSONDecodeError:
|
||||
@@ -127,6 +139,65 @@ def execute_strategy(request):
|
||||
}, status=500)
|
||||
|
||||
|
||||
def send_callback(execution):
|
||||
"""전략 실행 완료 후 콜백 URL로 결과 전송"""
|
||||
if not execution.callback_url:
|
||||
return
|
||||
|
||||
try:
|
||||
# 콜백 데이터 구성
|
||||
callback_data = {
|
||||
'execution_id': execution.id,
|
||||
'strategy': execution.strategy_version.strategy.name,
|
||||
'version': execution.strategy_version.version,
|
||||
'status': execution.status,
|
||||
'started_at': execution.started_at.isoformat(),
|
||||
'completed_at': execution.completed_at.isoformat() if execution.completed_at else None,
|
||||
'execution_parameters': execution.execution_parameters
|
||||
}
|
||||
|
||||
if execution.status == 'completed' and execution.result:
|
||||
callback_data['result'] = execution.result
|
||||
|
||||
if execution.status == 'failed' and execution.error_message:
|
||||
callback_data['error_message'] = execution.error_message
|
||||
|
||||
# POST 요청 전송 (타임아웃 10초)
|
||||
response = requests.post(
|
||||
execution.callback_url,
|
||||
json=callback_data,
|
||||
headers={'Content-Type': 'application/json'},
|
||||
timeout=10
|
||||
)
|
||||
|
||||
# 콜백 전송 결과 저장
|
||||
execution.callback_sent = True
|
||||
execution.callback_sent_at = timezone.now()
|
||||
execution.callback_response = {
|
||||
'status_code': response.status_code,
|
||||
'response_text': response.text[:500], # 처음 500자만 저장
|
||||
'headers': dict(response.headers)
|
||||
}
|
||||
execution.save()
|
||||
|
||||
logger.info(f"Callback sent successfully to {execution.callback_url} for execution {execution.id}")
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.error(f"Callback timeout for execution {execution.id} to {execution.callback_url}")
|
||||
execution.callback_response = {'error': 'timeout'}
|
||||
execution.save()
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Callback failed for execution {execution.id} to {execution.callback_url}: {str(e)}")
|
||||
execution.callback_response = {'error': str(e)}
|
||||
execution.save()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error sending callback for execution {execution.id}: {str(e)}")
|
||||
execution.callback_response = {'error': f'unexpected_error: {str(e)}'}
|
||||
execution.save()
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def execution_status(request, execution_id):
|
||||
execution = get_object_or_404(StrategyExecution, id=execution_id)
|
||||
@@ -149,6 +220,15 @@ def execution_status(request, execution_id):
|
||||
if execution.status == 'failed' and execution.error_message:
|
||||
response_data['error_message'] = execution.error_message
|
||||
|
||||
# 콜백 정보 추가
|
||||
if execution.callback_url:
|
||||
response_data['callback'] = {
|
||||
'url': execution.callback_url,
|
||||
'sent': execution.callback_sent,
|
||||
'sent_at': execution.callback_sent_at.isoformat() if execution.callback_sent_at else None,
|
||||
'response': execution.callback_response
|
||||
}
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user