feat: support Yumi activity runtime config
This commit is contained in:
parent
a2ff4768d3
commit
900a524f9b
86
.env
86
.env
@ -1,86 +0,0 @@
|
|||||||
APP_BIND=0.0.0.0
|
|
||||||
APP_PORT=2026
|
|
||||||
DEFAULT_REFRESH_INTERVAL_SECONDS=10
|
|
||||||
REFRESH_INTERVAL_OPTIONS=5,10,15,30,60
|
|
||||||
PROBE_TIMEOUT_SECONDS=3
|
|
||||||
PROBE_CACHE_TTL_SECONDS=5
|
|
||||||
PROBE_MAX_WORKERS=12
|
|
||||||
HOST_METRIC_CACHE_TTL_SECONDS=25
|
|
||||||
TAT_METRIC_TIMEOUT_SECONDS=30
|
|
||||||
TAT_CPU_SAMPLE_SECONDS=1
|
|
||||||
NACOS_BASE_URL=http://10.2.1.17:8848
|
|
||||||
NACOS_NAMESPACE_ID=f7a8594e-090c-4830-a3ad-b5c0f9afcc07
|
|
||||||
NACOS_NAMESPACE_NAME=RedCircleServiceProd
|
|
||||||
NACOS_DISCOVERY_GROUP=prod
|
|
||||||
NACOS_DISCOVERY_CLUSTER_NAME=DEFAULT
|
|
||||||
NACOS_CACHE_TTL_SECONDS=15
|
|
||||||
MONGO_URI=mongodb://root:123456@10.2.21.9:27017/tarab_all?authSource=admin&readPreference=secondaryPreferred&retryWrites=false&maxPoolSize=50&minPoolSize=5&maxIdleTimeMS=6000
|
|
||||||
MONGO_DB_NAME=tarab_all
|
|
||||||
MONGO_INSTANCE_ID=ins-o9mmob66
|
|
||||||
MONGO_CACHE_TTL_SECONDS=20
|
|
||||||
CPU_WARN_PERCENT=60
|
|
||||||
CPU_BAD_PERCENT=85
|
|
||||||
MEMORY_WARN_PERCENT=70
|
|
||||||
MEMORY_BAD_PERCENT=90
|
|
||||||
DISK_WARN_PERCENT=75
|
|
||||||
DISK_BAD_PERCENT=90
|
|
||||||
PROCESS_WARN_COUNT=180
|
|
||||||
PROCESS_BAD_COUNT=260
|
|
||||||
SERVICE_LATENCY_WARN_MS=1000
|
|
||||||
SERVICE_LATENCY_BAD_MS=3000
|
|
||||||
DEPLOY_REGION=me-saudi-arabia
|
|
||||||
TENCENT_SECRET_ID=IKIDMchhZEfrsiNo472DAtTpzzmLjttkOnyu
|
|
||||||
TENCENT_SECRET_KEY=nMkbLsGRO6ZqulSyJQJ0UjjU0KSKxOgl
|
|
||||||
GATEWAY_CLB_LOAD_BALANCER_ID=lb-cbiabr1q
|
|
||||||
GATEWAY_CLB_LISTENER_IDS=lbl-ktvz8m6k
|
|
||||||
GATEWAY_CLB_ALLOWED_DOMAINS=jvapi.haiyihy.com
|
|
||||||
GATEWAY_CLB_POLL_SECONDS=2
|
|
||||||
GATEWAY_CLB_TASK_TIMEOUT_SECONDS=120
|
|
||||||
GATEWAY_CLB_DRAIN_SECONDS=0
|
|
||||||
CDN_ALLOWED_DOMAINS=h5.haiyihy.com
|
|
||||||
CDN_PURGE_TASK_LIMIT=20
|
|
||||||
|
|
||||||
# Admin frontend deployment for Yumi
|
|
||||||
UPDATE_DEFAULT_ADMIN_GIT_REF=main
|
|
||||||
ADMIN_FRONTEND_ENABLED=1
|
|
||||||
ADMIN_FRONTEND_SERVICE_NAME=admin
|
|
||||||
ADMIN_FRONTEND_REPO_URL=git@gitea.haiyihy.com:hy/chatapp3-admin.git
|
|
||||||
ADMIN_FRONTEND_REPO_ROOT=/opt/deploy/sources/chatapp3-admin
|
|
||||||
ADMIN_FRONTEND_HOST=admin-platform
|
|
||||||
ADMIN_FRONTEND_IP=10.2.1.2
|
|
||||||
ADMIN_FRONTEND_INSTANCE_ID=ins-p11begwe
|
|
||||||
ADMIN_FRONTEND_SSH_HOST=10.2.1.2
|
|
||||||
ADMIN_FRONTEND_SSH_USER=root
|
|
||||||
ADMIN_FRONTEND_SSH_PORT=22
|
|
||||||
ADMIN_FRONTEND_SSH_USE_SUDO=0
|
|
||||||
ADMIN_FRONTEND_REMOTE_DIR=/opt/yumi-admin/frontend-admin
|
|
||||||
ADMIN_FRONTEND_SITE_DIR=/opt/yumi-admin/frontend-admin/site/yumiadmin-acc
|
|
||||||
ADMIN_FRONTEND_COMPOSE_FILE=/opt/yumi-admin/frontend-admin/docker-compose.yml
|
|
||||||
ADMIN_FRONTEND_COMPOSE_SERVICE=caddy
|
|
||||||
ADMIN_FRONTEND_RELEASE_META_PATH=/opt/yumi-admin/frontend-admin/.hy-app-monitor-admin-release.json
|
|
||||||
ADMIN_FRONTEND_BUILD_SCRIPT=build:antdv-next
|
|
||||||
ADMIN_FRONTEND_DIST_DIR=apps/dist
|
|
||||||
ADMIN_FRONTEND_PUBLIC_URL=https://yumiadmin-acc.global-interaction.com
|
|
||||||
CHATAPP_CRON_ENABLED=1
|
|
||||||
CHATAPP_CRON_REPO_URL=git@gitea.haiyihy.com:hy/chatapp-cron.git
|
|
||||||
CHATAPP_CRON_REPO_ROOT=/opt/deploy/sources/chatapp-cron
|
|
||||||
CHATAPP_CRON_DEFAULT_GIT_REF=main
|
|
||||||
CHATAPP_CRON_SERVICE_NAME=chatapp-cron
|
|
||||||
CHATAPP_CRON_HOST=cron-sg-1
|
|
||||||
CHATAPP_CRON_IP=10.3.1.14
|
|
||||||
CHATAPP_CRON_INSTANCE_ID=ins-nt6bsay0
|
|
||||||
CHATAPP_CRON_SSH_HOST=10.3.1.14
|
|
||||||
CHATAPP_CRON_SSH_USER=root
|
|
||||||
CHATAPP_CRON_SSH_PORT=22
|
|
||||||
CHATAPP_CRON_SSH_USE_SUDO=0
|
|
||||||
CHATAPP_CRON_REMOTE_DIR=/opt/likei/cron-sg-1
|
|
||||||
CHATAPP_CRON_COMPOSE_FILE=/opt/likei/cron-sg-1/docker-compose.yml
|
|
||||||
CHATAPP_CRON_COMPOSE_SERVICE=week-star-job
|
|
||||||
CHATAPP_CRON_BINARY_PATH=/opt/likei/cron-sg-1/week-star-job/service
|
|
||||||
CHATAPP_CRON_RELEASE_META_PATH=/opt/likei/cron-sg-1/.hy-app-monitor-chatapp-cron-release.json
|
|
||||||
|
|
||||||
# Harbor credentials for hy-app-monitor service update
|
|
||||||
HARBOR_REGISTRY=10.2.1.3:18082
|
|
||||||
HARBOR_PROJECT=likei
|
|
||||||
HARBOR_USERNAME=admin
|
|
||||||
HARBOR_PASSWORD=QkVXKcxCff_3x-pEkDCR_aAB
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ __pycache__/
|
|||||||
*.pyc
|
*.pyc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.venv/
|
.venv/
|
||||||
|
.env
|
||||||
|
|||||||
@ -83,6 +83,14 @@ GO_ENV_SPECS: list[dict[str, Any]] = [
|
|||||||
"aliases": ("GAME_JAVA_OTHER_BASE_URL", "INVITE_JAVA_APP_BASE_URL"),
|
"aliases": ("GAME_JAVA_OTHER_BASE_URL", "INVITE_JAVA_APP_BASE_URL"),
|
||||||
"kind": "string",
|
"kind": "string",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "Java",
|
||||||
|
"primary": "CHATAPP_JAVA_ORDER_BASE_URL",
|
||||||
|
# LIKEI_GATEWAY_ROUTE_ORDER_URI 只是 Go 的最后兜底,同时被 Java 网关消费;
|
||||||
|
# 不能把它当等价 alias 回写,否则保存 Go 配置会意外改掉共享网关路由。
|
||||||
|
"aliases": ("GAME_JAVA_ORDER_BASE_URL",),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "Java",
|
"section": "Java",
|
||||||
"primary": "CHATAPP_JAVA_WALLET_BASE_URL",
|
"primary": "CHATAPP_JAVA_WALLET_BASE_URL",
|
||||||
@ -329,6 +337,74 @@ GO_ENV_SPECS: list[dict[str, Any]] = [
|
|||||||
"aliases": ("WEEK_STAR_ROCKETMQ_TAG",),
|
"aliases": ("WEEK_STAR_ROCKETMQ_TAG",),
|
||||||
"kind": "string",
|
"kind": "string",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_DEFAULT_SYS_ORIGIN",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_DELIVERY_LEASE_SECONDS",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "positive_int",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENABLED",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "bool",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENDPOINT",
|
||||||
|
# LIKEI / WeekStar MQ key 仅是运行时兜底,不能作为可回写 alias;这些共享 key
|
||||||
|
# 还被其他消费者使用,Yumi 页面保存时必须只修改自己的命名空间。
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_NAMESPACE",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ACCESS_KEY",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ACCESS_SECRET",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_SECURITY_TOKEN",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_CONSUMER_GROUP",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_TOPIC",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "Yumi Gift Challenge MQ",
|
||||||
|
"primary": "CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_TAG",
|
||||||
|
"aliases": (),
|
||||||
|
"kind": "string",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "Baishun",
|
"section": "Baishun",
|
||||||
"primary": "CHATAPP_BAISHUN_PLATFORM_BASE_URL",
|
"primary": "CHATAPP_BAISHUN_PLATFORM_BASE_URL",
|
||||||
@ -557,6 +633,10 @@ def validate_scalar_kind(primary_key: str, value: str, kind: str) -> None:
|
|||||||
if kind == "int":
|
if kind == "int":
|
||||||
int(value)
|
int(value)
|
||||||
return
|
return
|
||||||
|
if kind == "positive_int":
|
||||||
|
if int(value) <= 0:
|
||||||
|
raise ValueError(f"{primary_key} must be a positive integer")
|
||||||
|
return
|
||||||
if kind == "bool":
|
if kind == "bool":
|
||||||
if value.strip().lower() not in {"1", "0", "true", "false", "yes", "no", "on", "off"}:
|
if value.strip().lower() not in {"1", "0", "true", "false", "yes", "no", "on", "off"}:
|
||||||
raise ValueError(f"{primary_key} must be a boolean")
|
raise ValueError(f"{primary_key} must be a boolean")
|
||||||
|
|||||||
@ -231,6 +231,9 @@ CHATAPP_WEEK_STAR_TIMEZONE=Asia/Riyadh
|
|||||||
CHATAPP_ROOM_TURNOVER_REWARD_TIMEZONE=Asia/Riyadh
|
CHATAPP_ROOM_TURNOVER_REWARD_TIMEZONE=Asia/Riyadh
|
||||||
CHATAPP_WEEK_STAR_SETTLE_INTERVAL_SECONDS=60
|
CHATAPP_WEEK_STAR_SETTLE_INTERVAL_SECONDS=60
|
||||||
CHATAPP_ROOM_TURNOVER_REWARD_SETTLE_INTERVAL_SECONDS=60
|
CHATAPP_ROOM_TURNOVER_REWARD_SETTLE_INTERVAL_SECONDS=60
|
||||||
|
CHATAPP_GAME_KING_SETTLE_INTERVAL_SECONDS=60
|
||||||
|
# Game King 每轮最多派送 4 组(单组硬超时 20 秒);120 秒为 DB 冻结和状态修复保留余量。
|
||||||
|
CHATAPP_GAME_KING_SETTLE_TIMEOUT_SECONDS=120
|
||||||
CHATAPP_WEEK_STAR_ROCKETMQ_ENABLED=false
|
CHATAPP_WEEK_STAR_ROCKETMQ_ENABLED=false
|
||||||
CHATAPP_WEEK_STAR_ROCKETMQ_ENDPOINT=rocketmq-proxy:8081
|
CHATAPP_WEEK_STAR_ROCKETMQ_ENDPOINT=rocketmq-proxy:8081
|
||||||
CHATAPP_WEEK_STAR_ROCKETMQ_ACCESS_KEY=test
|
CHATAPP_WEEK_STAR_ROCKETMQ_ACCESS_KEY=test
|
||||||
|
|||||||
@ -224,12 +224,18 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
# Game King 的 cron 只触发 Go 内部结算接口;等待健康后启动可避免发布窗口内的无效首轮请求。
|
||||||
|
golang:
|
||||||
|
condition: service_healthy
|
||||||
other:
|
other:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
wallet:
|
wallet:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
environment:
|
||||||
|
# 容器内 127.0.0.1 指向 cron 自身,必须使用 Compose 服务名访问 Golang。
|
||||||
|
CHATAPP_GO_BASE_URL: http://golang:2900
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
image: chatapp-test/admin:testbox
|
image: chatapp-test/admin:testbox
|
||||||
|
|||||||
@ -4,11 +4,86 @@ import unittest
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from core.config import HARBOR_PROJECT, HARBOR_REGISTRY, load_hosts
|
from core.config import HARBOR_PROJECT, HARBOR_REGISTRY, load_hosts
|
||||||
|
from monitors.yumi.runtime_config import (
|
||||||
|
GO_ENV_PRIMARY_BY_KEY,
|
||||||
|
GO_ENV_SPECS_BY_PRIMARY,
|
||||||
|
expand_host_updates,
|
||||||
|
validate_go_editor_content,
|
||||||
|
)
|
||||||
from monitors.yumi.service_release import build_update_targets_payload, deploy_updated_services_payload
|
from monitors.yumi.service_release import build_update_targets_payload, deploy_updated_services_payload
|
||||||
from monitors.yumi.service_ops import service_records_by_name
|
from monitors.yumi.service_ops import service_records_by_name
|
||||||
|
|
||||||
|
|
||||||
class ServiceReleaseTargetsTests(unittest.TestCase):
|
class ServiceReleaseTargetsTests(unittest.TestCase):
|
||||||
|
def test_yumi_activity_runtime_envs_are_editable_with_strict_types(self) -> None:
|
||||||
|
expected_keys = {
|
||||||
|
"CHATAPP_JAVA_ORDER_BASE_URL",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_DEFAULT_SYS_ORIGIN",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_DELIVERY_LEASE_SECONDS",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENABLED",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENDPOINT",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_NAMESPACE",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ACCESS_KEY",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ACCESS_SECRET",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_SECURITY_TOKEN",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_CONSUMER_GROUP",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_TOPIC",
|
||||||
|
"CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_TAG",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertTrue(expected_keys.issubset(GO_ENV_SPECS_BY_PRIMARY))
|
||||||
|
self.assertEqual(
|
||||||
|
GO_ENV_PRIMARY_BY_KEY["GAME_INTERNAL_CALLBACK_SECRET"],
|
||||||
|
"CHATAPP_HTTP_INTERNAL_CALLBACK_SECRET",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
GO_ENV_PRIMARY_BY_KEY["GAME_JAVA_ORDER_BASE_URL"],
|
||||||
|
"CHATAPP_JAVA_ORDER_BASE_URL",
|
||||||
|
)
|
||||||
|
|
||||||
|
valid = validate_go_editor_content(
|
||||||
|
"\n".join(
|
||||||
|
[
|
||||||
|
'CHATAPP_HTTP_INTERNAL_CALLBACK_SECRET="shared-secret"',
|
||||||
|
'GAME_JAVA_ORDER_BASE_URL="http://10.2.1.15:2600"',
|
||||||
|
'CHATAPP_YUMI_GIFT_CHALLENGE_DELIVERY_LEASE_SECONDS="300"',
|
||||||
|
'CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENABLED="true"',
|
||||||
|
'CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENDPOINT="rocketmq.example:8081"',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertTrue(valid["ok"])
|
||||||
|
self.assertEqual(valid["values"]["CHATAPP_JAVA_ORDER_BASE_URL"], "http://10.2.1.15:2600")
|
||||||
|
|
||||||
|
invalid_lease = validate_go_editor_content(
|
||||||
|
'CHATAPP_YUMI_GIFT_CHALLENGE_DELIVERY_LEASE_SECONDS="0"'
|
||||||
|
)
|
||||||
|
self.assertFalse(invalid_lease["ok"])
|
||||||
|
self.assertIn("positive integer", invalid_lease["message"])
|
||||||
|
|
||||||
|
invalid_enabled = validate_go_editor_content(
|
||||||
|
'CHATAPP_YUMI_GIFT_CHALLENGE_ROCKETMQ_ENABLED="enabled"'
|
||||||
|
)
|
||||||
|
self.assertFalse(invalid_enabled["ok"])
|
||||||
|
self.assertIn("must be a boolean", invalid_enabled["message"])
|
||||||
|
|
||||||
|
def test_game_king_legacy_env_shape_is_preserved_when_saved(self) -> None:
|
||||||
|
updates = expand_host_updates(
|
||||||
|
{
|
||||||
|
"GAME_INTERNAL_CALLBACK_SECRET": "old-secret",
|
||||||
|
"GAME_JAVA_ORDER_BASE_URL": "http://old-order:2600",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"CHATAPP_HTTP_INTERNAL_CALLBACK_SECRET": "new-secret",
|
||||||
|
"CHATAPP_JAVA_ORDER_BASE_URL": "http://new-order:2600",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(updates["GAME_INTERNAL_CALLBACK_SECRET"], "new-secret")
|
||||||
|
self.assertEqual(updates["GAME_JAVA_ORDER_BASE_URL"], "http://new-order:2600")
|
||||||
|
self.assertNotIn("CHATAPP_HTTP_INTERNAL_CALLBACK_SECRET", updates)
|
||||||
|
self.assertNotIn("CHATAPP_JAVA_ORDER_BASE_URL", updates)
|
||||||
|
|
||||||
def test_runtime_topology_keeps_singapore_cron_out_of_golang_release(self) -> None:
|
def test_runtime_topology_keeps_singapore_cron_out_of_golang_release(self) -> None:
|
||||||
hosts = load_hosts()
|
hosts = load_hosts()
|
||||||
cron_hosts = [host for host in hosts if host["host"] == "cron-sg-1"]
|
cron_hosts = [host for host in hosts if host["host"] == "cron-sg-1"]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user