forked from erp-dev/erp
feat: sse && multi_merchant completed
This commit is contained in:
96
sse/minimal_sse.py
Normal file
96
sse/minimal_sse.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
极简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
|
||||
Reference in New Issue
Block a user