4.3 KiB
4.3 KiB
ADR-002-02: Apex 代码编译和执行技术选型
状态
已接受
日期
2026-02-02
背景
Apex 代码编译和执行功能需要选择合适的技术方案,满足以下要求:
- 支持编译 Apex 类、触发器、编译并测试、执行匿名代码
- 支持查询编译历史、测试结果、代码覆盖率
- 保证多线程安全
- 与现有架构保持一致
- 支持历史数据查询和审计
决策
决策 1:数据持久化策略
选择方案 1:使用数据库持久化(MySQL),理由如下:
- 支持历史数据查询和审计需求
- 数据可靠性高,避免内存丢失
- 支持复杂的查询条件(时间范围、类型筛选等)
- 与现有 MyBatis Plus 技术栈一致
- 支持分页查询,性能可控
放弃方案 2(仅使用内存缓存)的理由:
- 服务重启后数据丢失
- 不支持历史数据查询
- 内存占用随数据量增加
- 无法满足审计需求
决策 2:结果处理方式
选择方案 1:直接使用 apex.jar 原生类,理由如下:
- 与 Salesforce API 完全兼容
- 减少不必要的封装层,降低复杂度
- 避免类型转换开销
- 与现有 Partner 模块保持一致的设计原则
- 代码更简洁,维护成本低
放弃方案 2(创建自定义封装层)的理由:
- 增加不必要的抽象层
- 需要维护额外的转换逻辑
- 增加开发工作量
- 与现有架构风格不一致
决策 3:并发控制策略
选择方案 1:使用 ReentrantLock,理由如下:
- 灵活性高,支持可中断、超时、公平锁等特性
- 性能优于 synchronized(在竞争激烈时)
- 支持条件变量,便于实现复杂的同步逻辑
- 与现有代码风格一致
放弃方案 2(synchronized 关键字)的理由:
- 灵活性较低
- 不支持超时机制
- 性能在竞争激烈时不如 ReentrantLock
放弃方案 3(数据库乐观锁)的理由:
- 增加数据库开销
- 需要额外维护版本号字段
- 对于编译操作,不需要严格的事务隔离
决策 4:数据库表设计
选择方案 1:4 张独立表(编译历史、测试结果、测试失败、代码覆盖率),理由如下:
- 符合数据库范式,避免数据冗余
- 每张表职责单一,易于维护
- 支持灵活的查询需求
- 与现有表设计规范一致
放弃方案 2(单表存储所有数据)的理由:
- 表结构复杂,字段过多
- 存在大量空值,浪费存储空间
- 查询性能差
- 不符合数据库设计规范
后果
正面影响
- 数据可靠性:使用数据库持久化,数据不会丢失
- 查询灵活性:支持复杂的历史数据查询
- 代码简洁性:直接使用原生类,减少封装层
- 性能可控:ReentrantLock 提供高性能的并发控制
- 维护成本低:与现有架构保持一致,开发人员熟悉
- 扩展性好:独立表设计便于后续扩展
负面影响
- 数据库开销:需要维护 4 张表,增加数据库负担
- 存储成本:历史数据需要占用存储空间
- 查询性能:大数据量时查询性能可能下降(可通过索引优化)
- 复杂度增加:需要处理数据库事务和并发控制
替代方案
方案 A:使用 Redis 缓存
- 优点:查询速度快,支持过期策略
- 缺点:数据可能丢失,不支持复杂查询,增加系统复杂度
- 适用场景:对查询速度要求极高,可接受数据丢失的场景
方案 B:使用 MongoDB
- 优点:灵活的文档模型,适合存储非结构化数据
- 缺点:增加新的技术栈,学习成本高,与现有架构不一致
- 适用场景:数据结构多变,需要灵活存储的场景
方案 C:使用消息队列异步处理
- 优点:解耦编译操作和持久化操作,提高响应速度
- 缺点:增加系统复杂度,需要处理消息丢失问题
- 适用场景:高并发场景,对响应速度要求高的场景
相关文档
- 需求文档
- 设计文档
- 连接管理 ADR - 连接管理技术选型(复用参考)
- Apex API 模块文档