Files
railwaysystem/docs/api-v2/09_external_adapter_contract.md
T

114 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RailwaySystem 外部系统适配器契约设计 (Integration Contract)
> **集成原则:** 真实设备与第三方系统一期全部采用 **Mock First** 原则。业务 Service 严禁直接硬编码外部 HTTP 接口,统一通过 **防腐适配器接口 (Adapter SPI)** 进行解耦与隔离。
> **外部调用解耦原则:** 数据库事务提交成功后,通过 `afterCommit` 触发后续 Adapter 调用(一期默认建议:`afterCommit` → 轻量异步执行器 → Adapter;若未引入异步执行器则为当前线程事务外调用 Adapter;两者皆保证外部调用失败不回滚已提交的本地数据库事务,而是独立更新同步状态并支持手工重试)。**MQ / Outbox / 分布式事务 = 一期不引入【扩展】。**
---
## 1. 适配器体系与 SPI 接口清单
系统抽象出三大核心集成适配器接口:
```mermaid
classDiagram
class FaceAttendanceAdapter {
<<interface>>
+pushLessonSchedule(PushScheduleCmd cmd) PushResult
+syncFaceFeature(SyncFaceCmd cmd) SyncResult
+mockCheckinCallback(MockCallbackCmd cmd) CallbackResult
}
class DoorAccessAdapter {
<<interface>>
+grantAccess(GrantAccessCmd cmd) AccessResult
+revokeAccess(RevokeAccessCmd cmd) AccessResult
+queryDeviceStatus(String lockSn) DeviceStatusResult
}
class ExternalLearningAdapter {
<<interface>>
+validateEventId(String sourceSystem, String eventId) boolean
+parseStudyPayload(Object rawPayload) StandardStudyEvent
+mockPushStudyDuration(MockStudyCmd cmd) PushResult
}
class MockFaceAttendanceAdapterImpl {
+pushLessonSchedule()
+syncFaceFeature()
}
class MockDoorAccessAdapterImpl {
+grantAccess()
+revokeAccess()
}
class MockExternalLearningAdapterImpl {
+validateEventId()
}
FaceAttendanceAdapter <|.. MockFaceAttendanceAdapterImpl
DoorAccessAdapter <|.. MockDoorAccessAdapterImpl
ExternalLearningAdapter <|.. MockExternalLearningAdapterImpl
```
---
## 2. 电子班牌与人脸考勤适配器:`FaceAttendanceAdapter`
### 2.1 业务场景
1. **课表向班牌推送:** 当教室排定课次后,系统将排课时段、授课教师及学员人脸凭证推送给对应教室的电子班牌;
2. **班牌签到打卡回传:** 学员在班牌刷脸后,班牌通过 HTTP 回调 RailwaySystem `/train/attendance/sign-in`。
### 2.2 接口规范与 Mock 行为
- **下发排课与人脸:** `PushResult pushLessonSchedule(PushScheduleCmd cmd)`
- **一期 Mock 实现【确认】:**
一期 Mock 实现直接打印日志并返回 `success: true`,模拟班牌下发成功;支持单元测试中模拟设备超时或离线。
---
## 3. 智能门禁与门锁适配器:`DoorAccessAdapter`
### 3.1 业务场景
学员完成宿舍分配后,系统下发人脸开锁授权;调房或退宿时,注销门锁权限。
### 3.2 接口规范
- **授权下发:** `AccessResult grantAccess(GrantAccessCmd cmd)`
- **权限撤销:** `AccessResult revokeAccess(RevokeAccessCmd cmd)`
- **轻量解耦与容灾重试设计【默认/建议方案】:**
1. 数据库事务提交成功后,通过 `afterCommit` 触发后续 Adapter 调用;
2. 一期默认建议:`afterCommit` → 轻量异步执行器 → Adapter;如果未引入异步执行器:`afterCommit` → 当前线程事务外调用 Adapter;
3. 两者都必须保证:外部调用失败不得回滚已经提交的本地数据库事务,而是保留/更新同步状态(`face_sync_status = 2`)并支持手工重试;
4. 明确:MQ / Outbox / 分布式事务 = 一期不引入【扩展】;
5. 单次 HTTP 请求超时阈值设为 5 秒,若调用失败或超时,在独立短事务中更新 `train_dorm_auth.face_sync_status = 2` (失败),记录 `last_error`,管理员可在页面一键手工重试。
---
## 4. VR / 3D / 电子阅览室学习记录接入:`ExternalLearningAdapter`
### 4.1 业务场景与幂等保证
外部专业实训系统在学员自主学习结束后,异步向 RailwaySystem 推送打卡流水。
### 4.2 接口响应三态设计 (HTTP 200)
- **正常首次接收 (`status = "accepted"`):**
```json
{
"code": 200,
"msg": "学习记录接入成功",
"data": { "status": "accepted", "durId": 5001, "message": "已记录学习时长 4500 秒" }
}
```
- **重复事件推送 (`status = "duplicate"`):**
```json
{
"code": 200,
"msg": "事件已存在,忽略重复推送",
"data": { "status": "duplicate", "durId": 5001, "message": "系统已存在该事件记录,无需重复入库" }
}
```
- **参数或拓扑非法 (`status = "invalid"`):**
```json
{
"code": 400,
"msg": "学习记录参数校验失败",
"data": { "status": "invalid", "durId": null, "message": "校验失败:startTime 不能晚于 endTime" }
}
```