feat(config-service): split config-service from iam for plugin/layout config
- new NestJS service on port 3011/gRPC 50059 (ADR-026) - owns 6 config_ tables (plugin/role-mapping/role-layout/layout-tpl/user-override/outbox) - GraphQL Federation 2 subgraph with DataLoader + RouterAuthGuard - gRPC ConfigService + admin REST CRUD + user REST API - three-layer merge: registry.defaultProps + roleMapping.widget_props + userOverride.props - Redis cache with 5min TTL - registered in apollo-router supergraph + docker-compose + port-allocation Implements M3 of v2.1 migration plan.
This commit is contained in:
@@ -40,3 +40,8 @@ subgraphs:
|
||||
routing_url: http://data-ana:3006/graphql
|
||||
schema:
|
||||
subgraph_url: http://data-ana:3006/graphql
|
||||
|
||||
config:
|
||||
routing_url: http://config-service:3011/graphql
|
||||
schema:
|
||||
subgraph_url: http://config-service:3011/graphql
|
||||
|
||||
@@ -294,6 +294,33 @@ services:
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_started
|
||||
config-service:
|
||||
build:
|
||||
context: ../services/config-service
|
||||
container_name: edu-config-service
|
||||
profiles: ["p3", "p4", "p5", "p6"]
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DATABASE_URL: mysql://edu:${MYSQL_PASSWORD:-changeme}@edu-mysql:3306/next_edu_cloud
|
||||
REDIS_URL: redis://edu-redis:6379
|
||||
KAFKA_BROKERS: kafka:29092
|
||||
ROUTER_AUTH_SECRET: ${ROUTER_AUTH_SECRET:-dev-router-secret}
|
||||
DEV_MODE: ${DEV_MODE:-false}
|
||||
PORT: "3011"
|
||||
GRPC_PORT: "50059"
|
||||
ports:
|
||||
- "3011:3011"
|
||||
- "50059:50059"
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3011/healthz"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
apollo-router:
|
||||
build:
|
||||
context: ./apollo-router
|
||||
@@ -313,6 +340,7 @@ services:
|
||||
- msg
|
||||
- ai
|
||||
- data-ana
|
||||
- config-service
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8088/health"]
|
||||
interval: 15s
|
||||
|
||||
@@ -733,3 +733,84 @@ CREATE TABLE IF NOT EXISTS `msg_announcement_reads` (
|
||||
UNIQUE KEY `uniq_announcement_user` (`announcement_id`, `user_id`),
|
||||
INDEX `idx_msg_announcement_reads_user` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- ============================================================
|
||||
-- 6. Config 服务(services/config-service/src/config-config/config.schema.ts)
|
||||
-- v2.1 M3 / ADR-026:从 iam 拆分出插件配置 + 布局 + 用户偏好职责
|
||||
-- ============================================================
|
||||
|
||||
-- 6.1 插件注册表(系统级,admin 维护;内置插件由构建脚本同步)
|
||||
CREATE TABLE IF NOT EXISTS `config_plugin_registry` (
|
||||
`plugin_id` VARCHAR(100) NOT NULL,
|
||||
`category` VARCHAR(50) NOT NULL,
|
||||
`version` VARCHAR(50) NULL,
|
||||
`display_name` VARCHAR(200) NOT NULL,
|
||||
`description` TEXT NULL,
|
||||
`required_roles` JSON NULL,
|
||||
`default_slot` VARCHAR(50) NULL,
|
||||
`default_size` JSON NULL,
|
||||
`default_props` JSON NULL,
|
||||
`props_schema` JSON NULL,
|
||||
`is_builtin` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`is_active` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`package_url` TEXT NULL,
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`plugin_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 6.2 角色-插件映射(admin 配置角色可用插件集 + 角色 Layout 默认)
|
||||
CREATE TABLE IF NOT EXISTS `config_role_plugin_mapping` (
|
||||
`role` VARCHAR(50) NOT NULL,
|
||||
`plugin_id` VARCHAR(100) NOT NULL,
|
||||
`slot` VARCHAR(50) NULL,
|
||||
`sort_order` INT NOT NULL DEFAULT 0,
|
||||
`is_enabled` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
`widget_props` JSON NULL,
|
||||
INDEX `idx_config_role_plugin_pk` (`role`, `plugin_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 6.3 角色 Layout 默认(admin 配置角色默认模板)
|
||||
CREATE TABLE IF NOT EXISTS `config_role_layout_default` (
|
||||
`role` VARCHAR(50) NOT NULL,
|
||||
`layout_id` VARCHAR(50) NOT NULL,
|
||||
`slot_overrides` JSON NULL,
|
||||
PRIMARY KEY (`role`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 6.4 Layout 模板(系统预置 5 种,不可改:classic/focus/split/triple/canvas)
|
||||
CREATE TABLE IF NOT EXISTS `config_layout_templates` (
|
||||
`layout_id` VARCHAR(50) NOT NULL,
|
||||
`display_name` VARCHAR(200) NOT NULL,
|
||||
`description` TEXT NULL,
|
||||
`available_slots` JSON NULL,
|
||||
`layout_schema` JSON NULL,
|
||||
`is_active` BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
PRIMARY KEY (`layout_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 6.5 用户布局覆盖(用户自定义)
|
||||
CREATE TABLE IF NOT EXISTS `config_user_layout_override` (
|
||||
`user_id` VARCHAR(36) NOT NULL,
|
||||
`active_layout` VARCHAR(50) NULL,
|
||||
`slot_overrides` JSON NULL,
|
||||
`plugin_placements` JSON NULL,
|
||||
`hidden_plugins` JSON NULL,
|
||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 6.6 Config Outbox 表(v2.1 ADR-032:业务写 outbox,Debezium 监听 binlog 投递 Kafka)
|
||||
CREATE TABLE IF NOT EXISTS `config_outbox` (
|
||||
`event_id` CHAR(36) NOT NULL,
|
||||
`aggregate_type` VARCHAR(50) NOT NULL,
|
||||
`aggregate_id` VARCHAR(100) NOT NULL,
|
||||
`event_type` VARCHAR(100) NOT NULL,
|
||||
`payload` JSON NOT NULL,
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`published_at` TIMESTAMP NULL,
|
||||
`retry_count` INT NOT NULL DEFAULT 0,
|
||||
`next_retry_at` TIMESTAMP NULL,
|
||||
PRIMARY KEY (`event_id`),
|
||||
INDEX `idx_outbox_unpublished` (`published_at`, `next_retry_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
@@ -37,21 +37,22 @@
|
||||
|
||||
## 3. NestJS BFF + 业务服务(3000-3099)
|
||||
|
||||
| 服务 | HTTP 端口 | gRPC 端口 | 说明 | 阶段 |
|
||||
| ------------- | --------- | --------- | ----------------------------------------------- | ------- |
|
||||
| apollo-router | 3000 | — | v2.1 GraphQL 聚合层(替代 BFF 手动聚合) | P3 |
|
||||
| iam | 3002 | 50052 | P2 启用 gRPC server(I1 裁决,2026-07-09 修正) | P2 ✅ |
|
||||
| teacher-bff | 3003 | — | BFF 不暴露 gRPC,对下游走 gRPC | P2 ✅ |
|
||||
| core-edu | 3004 | 50053 | 含原 classes 服务(合并后) | P3 |
|
||||
| content | 3005 | 50054 | Neo4j + ES | P4 |
|
||||
| data-ana | 3006 | 50055 | HTTP 保留作 Gateway 直连降级,gRPC 为 P4 主入口 | P4 |
|
||||
| msg | 3007 | 50056 | 通知中心 | P5 |
|
||||
| ai | 3008 | 50058 | LLM 网关 | P5 |
|
||||
| student-bff | 3009 | — | BFF 不暴露 gRPC | P3 |
|
||||
| parent-bff | 3010 | — | BFF 不暴露 gRPC | P4 |
|
||||
| ~~classes~~ | ~~3001~~ | ~~—~~ | 已合并入 core-edu(P3) | P1 历史 |
|
||||
| 服务 | HTTP 端口 | gRPC 端口 | 说明 | 阶段 |
|
||||
| -------------- | --------- | --------- | ----------------------------------------------- | ------- |
|
||||
| apollo-router | 3000 | — | v2.1 GraphQL 聚合层(替代 BFF 手动聚合) | P3 |
|
||||
| iam | 3002 | 50052 | P2 启用 gRPC server(I1 裁决,2026-07-09 修正) | P2 ✅ |
|
||||
| teacher-bff | 3003 | — | BFF 不暴露 gRPC,对下游走 gRPC | P2 ✅ |
|
||||
| core-edu | 3004 | 50053 | 含原 classes 服务(合并后) | P3 |
|
||||
| content | 3005 | 50054 | Neo4j + ES | P4 |
|
||||
| data-ana | 3006 | 50055 | HTTP 保留作 Gateway 直连降级,gRPC 为 P4 主入口 | P4 |
|
||||
| msg | 3007 | 50056 | 通知中心 | P5 |
|
||||
| ai | 3008 | 50058 | LLM 网关 | P5 |
|
||||
| student-bff | 3009 | — | BFF 不暴露 gRPC | P3 |
|
||||
| parent-bff | 3010 | — | BFF 不暴露 gRPC | P4 |
|
||||
| config-service | 3011 | 50059 | v2.1 M3 从 iam 拆分(ADR-026) | P3 |
|
||||
| ~~classes~~ | ~~3001~~ | ~~—~~ | 已合并入 core-edu(P3) | P1 历史 |
|
||||
|
||||
> **端口空闲**:3011-3099 预留扩展。
|
||||
> **端口空闲**:3012-3099 预留扩展。
|
||||
|
||||
---
|
||||
|
||||
@@ -82,9 +83,10 @@
|
||||
| data-ana | 50055 | AnalyticsService | P4 |
|
||||
| msg | 50056 | NotificationService / NotificationPreferenceService / NotificationTemplateService | P5 |
|
||||
| ai | 50058 | AiService | P5 |
|
||||
| config-service | 50059 | ConfigService | P3 |
|
||||
| ~~push-gateway~~ | ~~50057~~ | ~~PushService~~ | 豁免(见 §2) |
|
||||
|
||||
> **端口空闲**:50051、50057、50059-50099 预留扩展。
|
||||
> **端口空闲**:50051、50057、50060-50099 预留扩展。
|
||||
> **push-gateway 50057**:原计划预留,因 gRPC 豁免释放。50058 让给 ai 服务。
|
||||
|
||||
---
|
||||
@@ -116,12 +118,13 @@
|
||||
|
||||
## 7. 变更记录
|
||||
|
||||
| 日期 | 变更 | 决策者 |
|
||||
| ---------- | ------------------------------------------------------ | ------ |
|
||||
| 2026-07-09 | 初始创建,登记全部 15 服务 + 基础设施端口 | coord |
|
||||
| 2026-07-09 | 仲裁 admin-portal 3003 → 4003;MF 配置 3000 → 4000 | coord |
|
||||
| 2026-07-09 | 仲裁 push-gateway 豁免 gRPC,释放 50057;50058 让给 ai | coord |
|
||||
| 2026-07-09 | classes 3001 标记为历史(已合并入 core-edu) | coord |
|
||||
| 日期 | 变更 | 决策者 |
|
||||
| ---------- | --------------------------------------------------------- | ------ |
|
||||
| 2026-07-09 | 初始创建,登记全部 15 服务 + 基础设施端口 | coord |
|
||||
| 2026-07-09 | 仲裁 admin-portal 3003 → 4003;MF 配置 3000 → 4000 | coord |
|
||||
| 2026-07-09 | 仲裁 push-gateway 豁免 gRPC,释放 50057;50058 让给 ai | coord |
|
||||
| 2026-07-09 | classes 3001 标记为历史(已合并入 core-edu) | coord |
|
||||
| 2026-07-14 | M3 新增 config-service(3011/50059,ADR-026 从 iam 拆分) | coord |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user