union-app-chat-stream 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/.gitignore +16 -0
  2. package/PROJECT_OVERVIEW.md +187 -0
  3. package/app/.env +63 -0
  4. package/app/.env.dev +63 -0
  5. package/app/.env.prod.bj11 +63 -0
  6. package/app/.env.prod.sh20 +63 -0
  7. package/app/.env.prod.sz31 +63 -0
  8. package/app/.env.test.bj12 +63 -0
  9. package/app/__init__.py +42 -0
  10. package/app/__pycache__/__init__.cpython-312.pyc +0 -0
  11. package/app/__pycache__/authenticated_user.cpython-312.pyc +0 -0
  12. package/app/__pycache__/extensions.cpython-312.pyc +0 -0
  13. package/app/__pycache__/wsgi.cpython-312.pyc +0 -0
  14. package/app/authenticated_user.py +77 -0
  15. package/app/config/__pycache__/config_loader.cpython-312.pyc +0 -0
  16. package/app/config/__pycache__/env_config.cpython-312.pyc +0 -0
  17. package/app/config/__pycache__/logger_config.cpython-312.pyc +0 -0
  18. package/app/config/env_config.py +96 -0
  19. package/app/config/logger_config.py +46 -0
  20. package/app/manager/__init__.py +4 -0
  21. package/app/manager/__pycache__/__init__.cpython-312.pyc +0 -0
  22. package/app/manager/__pycache__/chatstream_manager.cpython-312.pyc +0 -0
  23. package/app/manager/__pycache__/prompts.cpython-312.pyc +0 -0
  24. package/app/manager/__pycache__/runtime_manager.cpython-312.pyc +0 -0
  25. package/app/manager/__pycache__/toolcall_manager.cpython-312.pyc +0 -0
  26. package/app/manager/chatstream_manager.py +90 -0
  27. package/app/manager/prompts.py +62 -0
  28. package/app/manager/runtime_manager.py +552 -0
  29. package/app/models/__pycache__/schemas.cpython-312.pyc +0 -0
  30. package/app/models/schemas.py +30 -0
  31. package/app/service/__init__.py +4 -0
  32. package/app/service/__pycache__/__init__.cpython-312.pyc +0 -0
  33. package/app/service/__pycache__/chat_service.cpython-312.pyc +0 -0
  34. package/app/service/__pycache__/llm_service.cpython-312.pyc +0 -0
  35. package/app/service/__pycache__/rag_service.cpython-312.pyc +0 -0
  36. package/app/service/__pycache__/tool_call_service.cpython-312.pyc +0 -0
  37. package/app/service/__pycache__/union_service.cpython-312.pyc +0 -0
  38. package/app/service/chat_service.py +228 -0
  39. package/app/service/llm_service.py +214 -0
  40. package/app/service/rag_service.py +866 -0
  41. package/app/service/union_service.py +201 -0
  42. package/app/utils/__init__.py +5 -0
  43. package/app/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  44. package/app/utils/__pycache__/common_utils.cpython-312.pyc +0 -0
  45. package/app/utils/__pycache__/debug_context.cpython-312.pyc +0 -0
  46. package/app/utils/__pycache__/function_utils.cpython-312.pyc +0 -0
  47. package/app/utils/__pycache__/jwt_utils.cpython-312.pyc +0 -0
  48. package/app/utils/common_utils.py +169 -0
  49. package/app/utils/debug_context.py +16 -0
  50. package/app/utils/function_utils.py +274 -0
  51. package/app/utils/jwt_utils.py +39 -0
  52. package/app/views/__init__.py +6 -0
  53. package/app/views/__pycache__/__init__.cpython-312.pyc +0 -0
  54. package/app/views/__pycache__/view_chatstream.cpython-312.pyc +0 -0
  55. package/app/views/__pycache__/view_healthcheck.cpython-312.pyc +0 -0
  56. package/app/views/__pycache__/view_runtime.cpython-312.pyc +0 -0
  57. package/app/views/view_chatstream.py +53 -0
  58. package/app/views/view_healthcheck.py +14 -0
  59. package/app/views/view_runtime.py +72 -0
  60. package/app/wsgi.py +37 -0
  61. package/ci.yml +14 -0
  62. package/deploy/autoconf/templates/env.j2 +25 -0
  63. package/deploy/autoconf.yml +15 -0
  64. package/deploy/scripts/healthcheck.sh +0 -0
  65. package/deploy/scripts/requirements.txt +53 -0
  66. package/deploy/scripts/start.sh +75 -0
  67. package/deploy/scripts/stop.sh +31 -0
  68. package/knowledge/.gitkeep +0 -0
  69. package/knowledge/000001-biz-offline-85b99bd43b-v1.md +88 -0
  70. package/knowledge/000002-biz-offline-717e8d823e-v1.md +90 -0
  71. package/knowledge/000003-biz-offline-c963227cc8-v1.md +84 -0
  72. package/knowledge/000004-biz-offline-2a5868e7da-v1.md +92 -0
  73. package/knowledge/000005-biz-offline-f9d9cf1a88-v1.md +79 -0
  74. package/knowledge/000006-biz-offline-c4fa2df3bd-v1.md +77 -0
  75. package/knowledge/000007-biz-offline-78304b70ca-v1.md +76 -0
  76. package/knowledge/000008-biz-offline-987ae67b35-v1.md +75 -0
  77. package/knowledge/000009-biz-offline-4d656bcea3-v1.md +85 -0
  78. package/knowledge/000010-sop-offline-a9e1050719-v1.md +100 -0
  79. package/knowledge/000011-biz-offline-5de0624891-v1.md +86 -0
  80. package/knowledge/000012-biz-offline-7dfacccba3-v1.md +82 -0
  81. package/knowledge/000013-biz-offline-5e1d29d2ed-v1.md +81 -0
  82. package/knowledge/000014-biz-offline-1d0ed8b841-v1.md +68 -0
  83. package/knowledge/000015-biz-offline-8a1376ee3e-v1.md +78 -0
  84. package/knowledge/000016-biz-offline-c8bfc2aa08-v1.md +99 -0
  85. package/knowledge/000017-biz-offline-9dffb28032-v1.md +88 -0
  86. package/knowledge/000018-biz-offline-f935bc9a6a-v1.md +80 -0
  87. package/knowledge/000019-biz-offline-858b3ecd89-v1.md +86 -0
  88. package/knowledge/000020-biz-offline-65cb5c4f40-v1.md +113 -0
  89. package/knowledge/000021-biz-offline-1bf211639c-v1.md +148 -0
  90. package/knowledge/000022-biz-offline-8c5a637879-v1.md +140 -0
  91. package/knowledge/000023-biz-offline-fe872b8712-v1.md +188 -0
  92. package/knowledge/000024-biz-offline-a85010c500-v1.md +133 -0
  93. package/knowledge/000025-biz-offline-8af58a3638-v1.md +136 -0
  94. package/knowledge/000026-biz-offline-6754102e93-v1.md +142 -0
  95. package/knowledge/000027-biz-offline-ea2e5ca5f9-v1.md +150 -0
  96. package/knowledge/000028-scenario-offline-dab45cebb4-v1.md +136 -0
  97. package/knowledge/000029-scenario-offline-5b8ae5ea9f-v1.md +143 -0
  98. package/knowledge/000030-scenario-offline-9a82d42f3f-v1.md +136 -0
  99. package/knowledge/000031-scenario-offline-cc2edc0197-v1.md +122 -0
  100. package/knowledge/000032-scenario-offline-e5f6e5cbfa-v1.md +122 -0
  101. package/knowledge/000033-scenario-offline-e1955849aa-v1.md +135 -0
  102. package/knowledge/000034-scenario-offline-3a13d49a3a-v1.md +138 -0
  103. package/knowledge/000035-scenario-offline-fd5560211f-v1.md +147 -0
  104. package/knowledge/000036-scenario-offline-function-call-mock-v1.md +134 -0
  105. package/package.json +18 -0
  106. package/requirements.txt +53 -0
  107. package/tools/prompts.yaml +10 -0
  108. package/tools/tool_definitions.yaml +303 -0
@@ -0,0 +1,39 @@
1
+ import jwt
2
+ from datetime import datetime, timedelta, timezone
3
+ from flask import current_app
4
+
5
+
6
+ def generate_jwt(user: str, attributes: dict = None) -> str:
7
+ now = datetime.now(timezone.utc)
8
+ payload = {
9
+ 'user': user,
10
+ 'iat': now,
11
+ 'exp': now + timedelta(seconds=current_app.config['JWT_EXPIRATION_SECOND'])
12
+ }
13
+ if attributes:
14
+ payload['attributes'] = attributes
15
+ token = jwt.encode(
16
+ payload,
17
+ current_app.config['JWT_SECRET_KEY'],
18
+ algorithm='HS256'
19
+ )
20
+ return token
21
+
22
+
23
+ def verify_jwt(token: str) -> dict:
24
+ try:
25
+ payload = jwt.decode(
26
+ token,
27
+ current_app.config['JWT_SECRET_KEY'],
28
+ algorithms=['HS256']
29
+ )
30
+ exp = datetime.fromtimestamp(payload['exp'], tz=timezone.utc)
31
+ now = datetime.now(timezone.utc)
32
+ # is_expired = now > exp
33
+ is_expiring_soon = (exp - now) < timedelta(seconds=current_app.config['JWT_RENEW_SECOND'])
34
+
35
+ return payload, is_expiring_soon
36
+ except jwt.ExpiredSignatureError:
37
+ raise Exception("Token expired")
38
+ except jwt.InvalidTokenError:
39
+ raise Exception("Invalid token")
@@ -0,0 +1,6 @@
1
+ from .view_chatstream import chatstream
2
+ from .view_runtime import runtime
3
+ from .view_healthcheck import healthcheck
4
+
5
+ __all__ = ["runtime", "healthcheck", "chatstream"]
6
+ blueprints = [runtime, healthcheck, chatstream]
@@ -0,0 +1,53 @@
1
+ from pydantic import ValidationError
2
+ from flask import Blueprint, current_app, request, Response, jsonify, stream_with_context, g
3
+
4
+ from app.models.schemas import ChatRequest, ChatResponse
5
+
6
+ chatstream = Blueprint("chatstream", __name__, url_prefix="/chatstream/v1")
7
+
8
+
9
+ def _sse_event(event: str, data: str) -> str:
10
+ return f"event: {event}\ndata: {data}\n\n"
11
+
12
+
13
+ def _chatstream_manager():
14
+ return current_app.extensions["chatstream_manager"]
15
+
16
+
17
+ @chatstream.get("/rag/check")
18
+ def rag_check():
19
+ return jsonify(_chatstream_manager().check_rag())
20
+
21
+
22
+ @chatstream.post("/rag/force-rebuild")
23
+ def rag_force_rebuild():
24
+ try:
25
+ return jsonify(_chatstream_manager().force_rebuild_rag())
26
+ except Exception as exc:
27
+ return jsonify({"detail": str(exc)}), 500
28
+
29
+
30
+ @chatstream.route("/chat/stream", methods=["OPTIONS", "POST"])
31
+ def chat_stream_endpoint():
32
+ if request.method == "OPTIONS":
33
+ return Response()
34
+
35
+ try:
36
+ chat_request = ChatRequest.model_validate(request.get_json(silent=True) or {})
37
+ except ValidationError as exc:
38
+ return jsonify({"detail": exc.errors()}), 422
39
+
40
+ def event_generator():
41
+ conversation_id = chat_request.conversation_id
42
+ jsessionid = g.current_user["jsessionid"]
43
+ for chunk in _chatstream_manager().chat_stream(conversation_id, chat_request.question, jsessionid):
44
+ conversation_id = chunk.conversation_id
45
+ yield _sse_event("message", chunk.model_dump_json(by_alias=True))
46
+
47
+ done = ChatResponse(conversationId=conversation_id, finish_reason="done")
48
+ yield _sse_event("done", done.model_dump_json(by_alias=True))
49
+
50
+ response = Response(stream_with_context(event_generator()), mimetype="text/event-stream")
51
+ response.headers.add("Cache-Control", "no-cache")
52
+ response.headers.add("Connection", "keep-alive")
53
+ return response
@@ -0,0 +1,14 @@
1
+ from flask import Blueprint
2
+ from loguru import logger
3
+
4
+ healthcheck = Blueprint('healthcheck', __name__)
5
+
6
+
7
+ @healthcheck.route('/healthcheck.html')
8
+ def health_check():
9
+ return "healthcheck ok"
10
+
11
+
12
+ @healthcheck.route('/favicon.ico')
13
+ def index():
14
+ return "", 204
@@ -0,0 +1,72 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Generator
4
+
5
+ from flask import Blueprint, current_app, request, Response, jsonify, g
6
+ from loguru import logger
7
+
8
+
9
+ runtime = Blueprint('runtime', __name__, url_prefix='/runtime/v1')
10
+
11
+
12
+ def _sse_event(data: str) -> str:
13
+ return f"data:{data}\n\n"
14
+
15
+
16
+ @runtime.route('/analyze', methods=['OPTIONS', 'POST'])
17
+ def analyze_runtime() -> Response:
18
+ """
19
+ 运行时分析接口
20
+
21
+ 接收用户查询文本,通过LLM分析系统运行质量,返回流式分析结果
22
+ 支持跨域请求(CORS)
23
+
24
+ Returns:
25
+ Flask Response对象,支持Server-Sent Events流式响应
26
+ """
27
+ # 处理预检请求(OPTIONS)
28
+ if request.method == 'OPTIONS':
29
+ return Response()
30
+
31
+ try:
32
+ # 获取登录态凭证和前端对话ID;runtime 不保存对话上下文。
33
+ jsessionid = g.current_user['jsessionid']
34
+ json_data = request.get_json(silent=True) or {}
35
+ query_content = json_data.get('text')
36
+ conversation_id = str(json_data.get('conversationId') or "").strip()
37
+
38
+ if not query_content:
39
+ error_response = jsonify({'error': '查询内容不能为空'})
40
+ error_response.headers.add('Access-Control-Allow-Origin', '*')
41
+ return error_response, 400
42
+
43
+ logger.info(f"接收到运行时分析请求: {query_content}")
44
+
45
+ manager = current_app.extensions["runtime_manager"]
46
+
47
+ # 执行完整的运行时分析流程
48
+ def generate() -> Generator[str, None, None]:
49
+ """生成流式响应"""
50
+ for message in manager.analyze_runtime_complete_stream(query_content, conversation_id, jsessionid):
51
+ yield _sse_event(message.model_dump_json(by_alias=True))
52
+
53
+ response = Response(generate(), mimetype='text/event-stream')
54
+
55
+ # 为流式响应添加CORS头部
56
+ response.headers.add('Access-Control-Allow-Origin', '*')
57
+ # SSE不需要缓存
58
+ response.headers.add('Cache-Control', 'no-cache')
59
+ response.headers.add('Connection', 'keep-alive')
60
+
61
+ return response
62
+
63
+ except KeyError as e:
64
+ logger.error(f"获取用户信息失败: {e}")
65
+ error_response = jsonify({'error': f'获取用户信息失败: {str(e)}'})
66
+ error_response.headers.add('Access-Control-Allow-Origin', '*')
67
+ return error_response, 401
68
+ except Exception as e:
69
+ logger.exception(f"分析运行时时发生异常: {e}")
70
+ error_response = jsonify({'error': f'服务器内部错误: {str(e)}'})
71
+ error_response.headers.add('Access-Control-Allow-Origin', '*')
72
+ return error_response, 500
package/app/wsgi.py ADDED
@@ -0,0 +1,37 @@
1
+ try:
2
+ from app import create_app
3
+
4
+ app = create_app()
5
+
6
+ from flask_cors import CORS
7
+
8
+ CORS(app, resources={
9
+ r"/.*": {
10
+ "origins": "*",
11
+ "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"],
12
+ "allow_headers": [
13
+ "Content-Type",
14
+ "Authorization",
15
+ "X-Requested-With",
16
+ "Accept",
17
+ "Origin",
18
+ "Access-Control-Request-Method",
19
+ "Access-Control-Request-Headers",
20
+ "Cookie",
21
+ "X-Session-Id",
22
+ ],
23
+ "expose_headers": [
24
+ "Content-Type",
25
+ "Authorization",
26
+ "X-Accel-Buffering",
27
+ ],
28
+ "max_age": 3600,
29
+ }
30
+ })
31
+ except Exception:
32
+ raise
33
+
34
+
35
+ if __name__ == '__main__':
36
+ if 'dev' in app.config["FLASK_ENV"]:
37
+ app.run(debug=True, host='0.0.0.0', port=8000)
package/ci.yml ADDED
@@ -0,0 +1,14 @@
1
+ Image:
2
+ type : default
3
+ BeforeBuild:
4
+ script :
5
+ Build:
6
+ script :
7
+ AfterBuild:
8
+ script :
9
+ Package:
10
+ script :
11
+ artifacts:
12
+ name : union-py-app
13
+ version : $COMMIT_ID-$BUILD_ID
14
+ files : [./app,./deploy,./scripts] # seperate multiple files by comma
@@ -0,0 +1,25 @@
1
+ FLASK_ENV={{FLASK_ENV}}
2
+ CONSOLE_STDOUT={{CONSOLE_STDOUT}}
3
+ LOG_LEVEL={{LOG_LEVEL}}
4
+ SECRET_KEY=
5
+
6
+ #JSESSION配置
7
+
8
+ #联合运维服务
9
+ GET_USE_INFO_URL={{GET_USE_INFO_URL}}
10
+ GET_ORG_INFO_URL={{GET_ORG_INFO_URL}}
11
+ GET_JIRA_INFO_URL={{GET_JIRA_INFO_URL}}
12
+ GET_BIGDATA_URL={{GET_BIGDATA_URL}}
13
+ GET_UNION_BASE_URL={{GET_UNION_BASE_URL}}
14
+
15
+ #大模型地址
16
+ LLM_URL={{LLM_URL}}
17
+ LLM_KEY={{LLM_KEY}}
18
+
19
+ #日志
20
+ LOG_DIR={{LOG_DIR}}
21
+
22
+ #JWT
23
+ JWT_SECRET_KEY=
24
+ JWT_EXPIRATION_SECOND={{JWT_EXPIRATION_SECOND}}
25
+ JWT_RENEW_SECOND={{JWT_RENEW_SECOND}}
@@ -0,0 +1,15 @@
1
+ union-py-app:
2
+ test:
3
+ test:
4
+ - template: deploy/autoconf/templates/env.j2
5
+ dest: env.test
6
+ prod:
7
+ bj11:
8
+ - template: deploy/autoconf/templates/env.j2
9
+ dest: env.prod
10
+ sh20:
11
+ - template: deploy/autoconf/templates/env.j2
12
+ dest: env.prod
13
+ sz31:
14
+ - template: deploy/autoconf/templates/env.j2
15
+ dest: env.prod
File without changes
@@ -0,0 +1,53 @@
1
+ annotated-types==0.7.0
2
+ anyio==4.6.2
3
+ blinker==1.8.2
4
+ certifi==2025.8.3
5
+ charset-normalizer==3.4.4
6
+ click==8.1.8
7
+ concurrent-log-handler==0.9.28
8
+ curlify==3.0.0
9
+ distro==1.9.0
10
+ dnspython==2.6.1
11
+ exceptiongroup==1.3.0
12
+ Flask==3.0.3
13
+ Flask-Cors==5.0.0
14
+ h11==0.16.0
15
+ h2==4.1.0
16
+ hpack==4.0.0
17
+ httpcore==1.0.9
18
+ httpx==0.28.1
19
+ Hypercorn==0.17.3
20
+ hyperframe==6.0.1
21
+ idna==3.10
22
+ itsdangerous==2.2.0
23
+ Jinja2==3.1.6
24
+ jiter==0.9.1
25
+ loguru==0.7.3
26
+ lxml==6.0.1
27
+ MarkupSafe==2.1.5
28
+ numpy>=2.0.0,<2.5.0
29
+ opencv-python>=4.13.0.90
30
+ openai==1.107.3
31
+ packaging==25.0
32
+ portalocker==3.0.0
33
+ priority==2.0.0
34
+ PyJWT==2.9.0
35
+ python-dateutil==2.9.0.post0
36
+ python-dotenv==1.0.1
37
+ pytz==2025.2
38
+ requests==2.32.5
39
+ six==1.17.0
40
+ sniffio==1.3.1
41
+ tqdm==4.67.3
42
+ typing_extensions==4.15.0
43
+ tzdata==2025.2
44
+ urllib3==1.26.20
45
+ Werkzeug==3.0.6
46
+ wsproto==1.2.0
47
+ zipp==3.20.2
48
+ pydantic==2.13.4
49
+ pyyaml==6.0.3
50
+ zai-sdk==0.2.2
51
+ chromadb==1.5.9
52
+ pysqlite3-binary==0.5.4
53
+ typer==0.15.1
@@ -0,0 +1,75 @@
1
+ #!/bin/bash
2
+ # 脚本:启动WSGI应用
3
+ # 功能:
4
+ # 1.检删除旧的union-py虚拟环境
5
+ # 2.创建新venv环境并安装依赖
6
+ # 3.启动WSGI服务
7
+ WSGI_APP="app.wsgi:app"
8
+ GUNICORN_CMD="gunicorn"
9
+ PYTHON="python"
10
+ LOG_ACCESS_FILE="/data/dataLogs/hypercorn_$(date '+%Y-%m-%d_%H_%M_%S').log"
11
+
12
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
13
+ VENV_DIR="$ROOT_DIR/union_py"
14
+ REQUIREMENTS="$ROOT_DIR/deploy/scripts/requirements.txt"
15
+ OFFLINK_PKGS="$ROOT_DIR/deploy/offline-packages"
16
+ PID_FILE="$ROOT_DIR/deploy/scripts/pid"
17
+ export PYTHONUNBUFFERED=1
18
+ export FLASK_ENV=$(head -n 1 "$ROOT_DIR/deploy/scripts/start.sh")
19
+ echo "切换到项目目录$ROOT_DIR 并设置FLASK_ENV环境变量:$FLASK_ENV" >> "$LOG_ACCESS_FILE"
20
+ #$ pip3 download -r deploy/scripts/requirements.txt --only-binary=:all: --platform manylinux2014_x86_64 --python-version 38 --abi cp38 --implementation cp -d ddd --trusted-host pypi.nucc.com
21
+ #wget http://mirrors.nucc.com/repo/pip.conf -O /home/nucc/.pip/pip.conf
22
+ #/usr/local/python3.8.5/bin/python3.8 -m pip install --upgrade pip
23
+
24
+ BIND_PORT="127.0.0.1"
25
+ if [[ "$FLASK_ENV" == *test* ]]; then
26
+ BIND_PORT="0.0.0.0"
27
+ fi
28
+ echo "开始启动,当前目录:$(pwd)...." >> "$LOG_ACCESS_FILE"
29
+ if [ -d "$VENV_DIR" ]; then
30
+ echo "删除现有环境:$VENV_DIR" >> "$LOG_ACCESS_FILE"
31
+ rm -rf "$VENV_DIR"
32
+ else
33
+ echo "虚拟环境$VENV_DIR 不存在,跳过删除" >> "$LOG_ACCESS_FILE"
34
+ fi
35
+ echo "开始创建虚拟环境$VENV_DIR " >> "$LOG_ACCESS_FILE"
36
+ $PYTHON -m venv "$VENV_DIR"
37
+ if [ $? -ne 0 ]; then
38
+ echo "创建虚拟环境$VENV_DIR 失败,请检查python3 和venv命令是否可用" >> "$LOG_ACCESS_FILE"
39
+ exit 1
40
+ fi
41
+ source "$VENV_DIR/bin/activate"
42
+ echo "虚拟环境$VENV_DIR 创建成功.并已激活虚拟环境$VENV_DIR" >> "$LOG_ACCESS_FILE"
43
+
44
+ echo "安装依赖 from $REQUIREMENTS 文件" >> "$LOG_ACCESS_FILE"
45
+ if [ ! -f "$REQUIREMENTS" ]; then
46
+ echo "$REQUIREMENTS 文件不存在,退出" >> "$LOG_ACCESS_FILE"
47
+ exit 1
48
+ fi
49
+ pip install \
50
+ --no-index \
51
+ --find-links "$OFFLINK_PKGS" \
52
+ --no-cache-dir \
53
+ -r "$REQUIREMENTS" || { echo "依赖安装失败,请检查离线包是否完整" >> "$LOG_ACCESS_FILE"; exit 1 ;}
54
+
55
+ echo "安装依赖完成。启动WSGI应用:$WSGI_APP" >> "$LOG_ACCESS_FILE"
56
+ cd "$ROOT_DIR"
57
+ hypercorn \
58
+ --workers 4 \
59
+ --bind "$BIND_PORT":8000 \
60
+ --keep-alive 2 \
61
+ --pid "$PID_FILE" \
62
+ "$WSGI_APP" \
63
+ >> "$LOG_ACCESS_FILE" 2>&1 &
64
+ echo $! >> "$LOG_ACCESS_FILE"
65
+
66
+ for i in $(seq 1 5);do
67
+ if [ -f "$PID_FILE" ] ;then
68
+ PID=$(cat "$PID_FILE" 2>/dev/null)
69
+ if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null ; then
70
+ echo "hypercorn 已启动 (PID:$PID)"
71
+ exit 0
72
+ fi
73
+ fi
74
+ sleep 1
75
+ done
@@ -0,0 +1,31 @@
1
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
2
+
3
+ PID_FILE="$ROOT_DIR/deploy/scripts/pid"
4
+
5
+ quiet_stop(){
6
+ if [ ! -f "$PID_FILE" ];then
7
+ return 0
8
+ fi
9
+ PID=$(cat "$PID_FILE" 2>/dev/null)
10
+ if [ -z "$PID" ];then
11
+ rm -f "$PID_FILE"
12
+ return 0
13
+ fi
14
+ if kill -0 "$PID" 2>/dev/null; then
15
+ echo "正在停止 hypercorn(PID:$PID)..."
16
+ kill "$PID" >/dev/null 2>&1
17
+ for i in {1..5}; do
18
+ if ! kill -0 "$PID" 2>/dev/null; then
19
+ echo "hypercorn(PID:$PID) 已停止"
20
+ rm -f "$PID_FILE"
21
+ return 0
22
+ fi
23
+ sleep 1
24
+ done
25
+ echo "兜底,强制停止"
26
+ kill -9 "$PID" 2>/dev/null
27
+ fi
28
+ rm -f "$PID_FILE"
29
+ }
30
+
31
+ quiet_stop
File without changes
@@ -0,0 +1,88 @@
1
+ ---
2
+ kb_id: biz-offline-85b99bd43b-v1
3
+ title: Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
4
+ doc_type: biz
5
+ domain: 联合运维
6
+ category: Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
7
+ category_description: 本分类来源于《Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3》,主要覆盖:网络支付清算平台
8
+ 联合运维互联互通技术规范;1 范围;2 规范性引用文件;3 术语和定义;3.1 网络支付清算平台 electronics payment clearing of
9
+ China;3.2 联合运维成员单位;3.3 报文 message;4 通讯规范。
10
+ category_keywords:
11
+ - NUC
12
+ - '601'
13
+ - '2023'
14
+ - 网络支付清算平台
15
+ - 联合运维互联互通技术规范V1.3
16
+ - Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
17
+ - 联合运维互联互通技术规范
18
+ - 网络支付清算平台 联合运维互联互通技术规范
19
+ - 范围
20
+ - 1 范围
21
+ - 规范性引用文件
22
+ - 2 规范性引用文件
23
+ - 术语和定义
24
+ - 3 术语和定义
25
+ - '3.1'
26
+ - electronics
27
+ business_modules:
28
+ - 网络支付清算平台
29
+ - 联合运维互联互通技术规范V1.3
30
+ source_doc: 互联互通机制规范.md
31
+ source_version: V1.3
32
+ source_section: Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
33
+ source_order: 1
34
+ source_pages: []
35
+ source_trace: section=Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
36
+ effective_date: ''
37
+ owner: 联合运维知识库
38
+ confidentiality: 内部
39
+ risk_level: low
40
+ applicable_roles: []
41
+ tags:
42
+ - NUC
43
+ - '601'
44
+ - '2023'
45
+ - 网络支付清算平台
46
+ - 联合运维互联互通技术规范V1.3
47
+ - Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
48
+ - 联合运维互联互通技术规范
49
+ - 网络支付清算平台 联合运维互联互通技术规范
50
+ - 范围
51
+ - 1 范围
52
+ - 规范性引用文件
53
+ - 2 规范性引用文件
54
+ - 术语和定义
55
+ - 3 术语和定义
56
+ - '3.1'
57
+ - electronics
58
+ status: active
59
+ ---
60
+
61
+ # Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
62
+
63
+ 知识大类说明:
64
+ 大类:Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
65
+ 说明:本分类来源于《Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3》,主要覆盖:网络支付清算平台 联合运维互联互通技术规范;1 范围;2 规范性引用文件;3 术语和定义;3.1 网络支付清算平台 electronics payment clearing of China;3.2 联合运维成员单位;3.3 报文 message;4 通讯规范。
66
+ 关键词:NUC、601、2023、网络支付清算平台、联合运维互联互通技术规范V1.3、Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3、联合运维互联互通技术规范、网络支付清算平台 联合运维互联互通技术规范、范围、1 范围、规范性引用文件、2 规范性引用文件、术语和定义、3 术语和定义、3.1、electronics
67
+
68
+ ## 1. 核心内容
69
+
70
+ 本规范规定了联合运维成员单位通过系统对接方式接入网络支付清算平台开展联合运维工作所需报文格式、报文使用规则、报文结构及报文交换流程的等。本规范适用于联合运维成员单位通过系统对接方式接入网络支付清算平台开展联合运维工作的需求分析、系统设计和开发测试。
71
+
72
+ ## 2. 适用边界
73
+
74
+ 本规范适用于联合运维成员单位通过系统对接方式接入网络支付清算平台开展联合运维工作的需求分析、系统设计和开发测试。
75
+
76
+ ## 3. 使用要求
77
+
78
+ 暂无
79
+
80
+ ## 4. 关联能力
81
+
82
+ 暂无。
83
+
84
+ ## 5. 来源依据
85
+
86
+ - 来源文档:互联互通机制规范.md
87
+ - 来源章节:Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
88
+ - 来源说明:基于来源章节归纳,需人工复核原文一致性。
@@ -0,0 +1,90 @@
1
+ ---
2
+ kb_id: biz-offline-717e8d823e-v1
3
+ title: Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3 范围
4
+ doc_type: biz
5
+ domain: 联合运维
6
+ category: Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
7
+ category_description: 本分类来源于《Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3》,主要覆盖:网络支付清算平台
8
+ 联合运维互联互通技术规范;1 范围;2 规范性引用文件;3 术语和定义;3.1 网络支付清算平台 electronics payment clearing of
9
+ China;3.2 联合运维成员单位;3.3 报文 message;4 通讯规范。
10
+ category_keywords:
11
+ - NUC
12
+ - '601'
13
+ - '2023'
14
+ - 网络支付清算平台
15
+ - 联合运维互联互通技术规范V1.3
16
+ - Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
17
+ - 联合运维互联互通技术规范
18
+ - 网络支付清算平台 联合运维互联互通技术规范
19
+ - 范围
20
+ - 1 范围
21
+ - 规范性引用文件
22
+ - 2 规范性引用文件
23
+ - 术语和定义
24
+ - 3 术语和定义
25
+ - '3.1'
26
+ - electronics
27
+ business_modules:
28
+ - 网络支付清算平台
29
+ - 联合运维互联互通技术规范V1.3
30
+ source_doc: 互联互通机制规范.md
31
+ source_version: V1.3
32
+ source_section: 1 范围
33
+ source_order: 2
34
+ source_pages: []
35
+ source_trace: section=1 范围
36
+ effective_date: ''
37
+ owner: 联合运维知识库
38
+ confidentiality: 内部
39
+ risk_level: low
40
+ applicable_roles: []
41
+ tags:
42
+ - NUC
43
+ - '601'
44
+ - '2023'
45
+ - 网络支付清算平台
46
+ - 联合运维互联互通技术规范V1.3
47
+ - Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
48
+ - 联合运维互联互通技术规范
49
+ - 网络支付清算平台 联合运维互联互通技术规范
50
+ - 范围
51
+ - 1 范围
52
+ - 规范性引用文件
53
+ - 2 规范性引用文件
54
+ - 术语和定义
55
+ - 3 术语和定义
56
+ - '3.1'
57
+ - electronics
58
+ status: active
59
+ ---
60
+
61
+ # Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3 范围
62
+
63
+ 知识大类说明:
64
+ 大类:Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3
65
+ 说明:本分类来源于《Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3》,主要覆盖:网络支付清算平台 联合运维互联互通技术规范;1 范围;2 规范性引用文件;3 术语和定义;3.1 网络支付清算平台 electronics payment clearing of China;3.2 联合运维成员单位;3.3 报文 message;4 通讯规范。
66
+ 关键词:NUC、601、2023、网络支付清算平台、联合运维互联互通技术规范V1.3、Q/NUC 601-2023 网络支付清算平台 联合运维互联互通技术规范V1.3、联合运维互联互通技术规范、网络支付清算平台 联合运维互联互通技术规范、范围、1 范围、规范性引用文件、2 规范性引用文件、术语和定义、3 术语和定义、3.1、electronics
67
+
68
+ ## 1. 核心内容
69
+
70
+ 本规范规定了联合运维成员单位通过系统对接方式接入网络支付清算平台开展联合运维工作所需报文格式、报文使用规则、报文结构及报文交换流程的等。
71
+
72
+ 本规范适用于联合运维成员单位通过系统对接方式接入网络支付清算平台开展联合运维工作的需求分析、系统设计和开发测试。
73
+
74
+ ## 2. 适用边界
75
+
76
+ 适用于联合运维成员单位通过系统对接方式接入网络支付清算平台开展联合运维工作的需求分析、系统设计和开发测试。
77
+
78
+ ## 3. 使用要求
79
+
80
+ 暂无
81
+
82
+ ## 4. 关联能力
83
+
84
+ 暂无。
85
+
86
+ ## 5. 来源依据
87
+
88
+ - 来源文档:互联互通机制规范.md
89
+ - 来源章节:1 范围
90
+ - 来源说明:基于来源章节归纳,需人工复核原文一致性。