VTJ.PRO 在线应用开发平台的DSL生命周期

0 阅读3分钟

DSL 生命周期:从开发到生产

本文档记录了 VTJ.PRO 平台中领域特定语言(DSL)实体的生命周期。它详细说明了 DslService 如何管理应用程序模式从开发环境到生产环境的过渡,包括同步、历史跟踪和批处理。

1. DSL 实体概述

该平台将低代码应用、物料和文件表示为 DSL 对象。这些对象通过 DslEntity 持久化到数据库中,并通过 DslType 枚举进行分类。

DslType 类别

DslType 定义了 DSL 记录的范围和目的:

类型描述
Project0低代码项目的根配置。
Material1组件元数据和物料库定义。
File2单个页面或组件 DSL 文件。
History3用于版本回滚的文件快照。

环境隔离

每个 DSL 实体跟踪其内容的两个不同版本:

  • content: 开发环境中的当前工作版本。
  • prod: 当前部署到生产环境的版本。

2. DSL 生命周期工作流

生命周期由 DslService 管理,它提供了更新开发草稿、发布到生产以及还原更改的方法。

开发到生产(发布)

publishFromDev 方法将开发环境中的 content 同步到 prod 字段。这个过程有效地将当前的开发状态“发布”到生产运行时。

工作流:

  1. 通过 ID 检索实体。
  2. content 的值赋给 prod
  3. 保存更新后的实体。

生产到开发(还原)

copyToDev 方法执行相反的操作,允许开发者通过用稳定的 prod 数据覆盖 content 来丢弃开发环境中的实验性更改。

逻辑流程:开发/生产同步

下图说明了单个 DslEntity 内部开发和生产状态之间的数据流。

DSL 状态转换

flowchart
    subgraph DslEntity
        DevContent["content (Dev Draft)"]
        ProdContent["prod (Production)"]
    end
    User -->|"saveDsl()"| DevContent
    DevContent -->|"publishFromDev()"| ProdContent
    ProdContent -->|"copyToDev()"| DevContent

3. 实现细节:DslService

DslService 扩展了 BaseCrudService,并处理复杂操作,如历史创建和项目文件的批量更新。

主要方法

方法描述
saveDsl更新 DSL 实体的 content。如果类型是 File,它会自动创建一个 History 条目。
publishFromDev将特定实体的 content 移动到 prod
publishApp批量发布与特定 appId 关联的所有 DSL 实体(项目、物料和文件)。
copyToDevprod 恢复 content
recovery从特定的 History 实体中恢复文件的 content

代码实体映射

此图将服务逻辑与底层的 TypeORM 实体联系起来。

服务到实体映射

flowchart
    subgraph API Layer
        DslController
    end
    subgraph Service Layer
        DslService
    end
    subgraph Data Layer
        DslRepo[Repository<DslEntity>]
        DslEntity
    end
    DslController -->|Calls| DslService
    DslService -->|Manipulates| DslRepo
    DslRepo -->|Persists| DslEntity

4. 历史记录和版本控制

当通过 saveDsl 保存一个类型为 File 的 DSL 时,系统不仅仅会覆盖 content。它会创建一个快照以确保数据安全。

  1. 检查类型: 服务检查 DslType === DslType.File
  2. 创建历史: 实例化一个新的 DslEntity,其 type: DslType.History
  3. 链接引用: 历史记录的 parentId 设置为原始文件的 ID。
  4. 保留: 系统维护一个变更历史,可以通过 recovery 方法查看或恢复。

5. 批处理策略

发布整个应用程序需要同步多个相关实体。publishApp 方法通过定位与 appId 链接的所有 DSL 记录来自动完成此操作。

async publishApp(appId: string) {
  return await this.repository.update(
    { appId },
    {
      prod: () => 'content', // TypeORM 原生 SQL 表达式,用于复制列
      updateTime: new Date(),
    },
  );
}

这种方法可确保项目配置、物料定义和所有文件在单个数据库操作中更新到生产环境,从而保持应用程序运行时的一致性。

参考资料