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

113 lines
4.8 KiB
Markdown
Raw Normal View History

# 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" }
}
```