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

4.8 KiB
Raw Blame History

RailwaySystem 外部系统适配器契约设计 (Integration Contract)

集成原则: 真实设备与第三方系统一期全部采用 Mock First 原则。业务 Service 严禁直接硬编码外部 HTTP 接口,统一通过 防腐适配器接口 (Adapter SPI) 进行解耦与隔离。 外部调用解耦原则: 数据库事务提交成功后,通过 afterCommit 触发后续 Adapter 调用(一期默认建议:afterCommit → 轻量异步执行器 → Adapter;若未引入异步执行器则为当前线程事务外调用 Adapter;两者皆保证外部调用失败不回滚已提交的本地数据库事务,而是独立更新同步状态并支持手工重试)。MQ / Outbox / 分布式事务 = 一期不引入【扩展】。


1. 适配器体系与 SPI 接口清单

系统抽象出三大核心集成适配器接口:

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"):
    {
      "code": 200,
      "msg": "学习记录接入成功",
      "data": { "status": "accepted", "durId": 5001, "message": "已记录学习时长 4500 秒" }
    }
    
  • 重复事件推送 (status = "duplicate"):
    {
      "code": 200,
      "msg": "事件已存在,忽略重复推送",
      "data": { "status": "duplicate", "durId": 5001, "message": "系统已存在该事件记录,无需重复入库" }
    }
    
  • 参数或拓扑非法 (status = "invalid"):
    {
      "code": 400,
      "msg": "学习记录参数校验失败",
      "data": { "status": "invalid", "durId": null, "message": "校验失败:startTime 不能晚于 endTime" }
    }