1
0
forked from erp-dev/erp
Files
erpnew/sse/minimal_sse.py

96 lines
3.0 KiB
Python

"""
极简SSE实现 - 专注于快速关闭
关键原则:
1. 不使用任何全局状态或复杂的队列系统
2. 使用最短的超时时间
3. 依靠HTTP连接的自然断开机制
"""
import json
import time
import signal
import threading
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
# 简单的全局关闭标志
shutdown_requested = threading.Event()
def trigger_shutdown():
"""触发全局关闭"""
shutdown_requested.set()
def is_shutdown_requested():
"""检查是否请求关闭"""
return shutdown_requested.is_set()
@csrf_exempt
def minimal_sse_view(request):
"""极简SSE视图 - 专注于快速响应关闭信号"""
if request.method == 'OPTIONS':
response = HttpResponse()
origin = request.META.get('HTTP_ORIGIN')
if origin:
response['Access-Control-Allow-Origin'] = origin
response['Access-Control-Allow-Methods'] = 'GET, OPTIONS'
response['Access-Control-Allow-Headers'] = 'authorization, content-type'
response['Access-Control-Allow-Credentials'] = 'true'
return response
def quick_stream():
"""快速响应的流生成器"""
try:
# 发送连接消息
yield f"data: {json.dumps({'type': 'connected', 'time': time.time()})}\n\n"
# 极短循环 - 每0.2秒检查关闭信号
counter = 0
while not shutdown_requested.is_set():
counter += 1
# 每5次循环(1秒)发送心跳
if counter % 5 == 0:
yield f": heartbeat\n\n"
# 非常短的睡眠,快速响应关闭
time.sleep(0.2)
# 最多运行100次循环(20秒)后自动断开,防止永久阻塞
if counter > 100:
break
# 发送关闭消息
yield f"data: {json.dumps({'type': 'closing'})}\n\n"
except GeneratorExit:
pass
except Exception as e:
print(f"SSE stream error: {e}")
response = HttpResponse(quick_stream(), content_type='text/event-stream')
response['Cache-Control'] = 'no-cache, no-store'
response['Connection'] = 'close' # 明确告诉客户端这是短连接
origin = request.META.get('HTTP_ORIGIN')
if origin:
response['Access-Control-Allow-Origin'] = origin
response['Access-Control-Allow-Credentials'] = 'true'
return response
# 注册简单的信号处理器
def setup_minimal_handlers():
def handle_shutdown(signum, frame):
print(f"Minimal SSE: received signal {signum}")
trigger_shutdown()
signal.signal(signal.SIGTERM, handle_shutdown)
signal.signal(signal.SIGINT, handle_shutdown)
# 立即设置处理器
try:
setup_minimal_handlers()
print("Minimal SSE handlers registered")
except:
pass