返回博客

ObjectType 生命周期:从 DRAFT 到 ARCHIVED 的状态机

在传统开发中,数据库 Schema 变更是一个危险的操作:

Coomia发布于 2025年8月6日17 分钟阅读
分享本文Twitter / X

ObjectType 生命周期:从 DRAFT 到 ARCHIVED 的状态机

系列:S4 本体建模 · 第 3 篇 | 难度:中级 | 阅读时间:18 分钟

#TL;DR

  • **Schema 生命周期四阶段(DRAFT → ACTIVE → DEPRECATED → ARCHIVED)**确保了 Ontology 变更的安全性和可追溯性,每次状态转换都有严格的前置条件检查。
  • 兼容性验证引擎在每次变更时自动检测破坏性更改(删除必填属性、修改主键类型等),防止"改了 Schema 却没改消费者"的灾难性场景。
  • 安全删除协议通过依赖图分析确保被删除的类型不会留下悬挂引用,支持 dry-run 预检和强制删除两种模式。

#1. 为什么 Schema 需要生命周期管理

在传统开发中,数据库 Schema 变更是一个危险的操作:

Code
传统方式(危险):
┌─────────────┐
│  ALTER TABLE │ → 立即生效
│  DROP COLUMN │ → 无法回退
│  RENAME      │ → 消费者全挂
└─────────────┘

开发者:写个 Flyway 脚本 → DBA 审核(也许)→ 直接执行 → 祈祷不出事

coomia-dip 方式(安全):
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│    DRAFT     │───►│   ACTIVE    │───►│ DEPRECATED  │───►│  ARCHIVED   │
│  (草稿)      │    │  (生产可用)  │    │  (计划下线)  │    │  (已归档)    │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
  可自由修改         兼容性变更only      通知消费者迁移      只读,不可修改

#2. 四个生命周期状态详解

#2.1 DRAFT — 草稿状态

Code
┌──────────────────────────────────────┐
│              DRAFT                    │
│                                      │
│  特性:                               │
│  ├── 可以自由添加/删除/修改属性         │
│  ├── 可以修改主键定义                  │
│  ├── 可以修改关系定义                  │
│  ├── 不会生成 API                     │
│  ├── 不会创建物理存储                  │
│  └── 可以直接删除(无需依赖检查)       │
│                                      │
│  可用操作:                            │
│  ├── addProperty                     │
│  ├── removeProperty                  │
│  ├── modifyProperty                  │
│  ├── setPrimaryKey                   │
│  ├── addRelation                     │
│  ├── publish  → 转为 ACTIVE          │
│  └── delete   → 永久删除             │
└──────────────────────────────────────┘
Python
from ontology_sdk import OntologyClient

client = OntologyClient(base_url="http://localhost:8080")

# 创建 DRAFT 状态的 ObjectType
result = client.schema.create_object_type({
    "name": "Equipment",
    "primaryKey": "equipmentId",
    "properties": {
        "equipmentId": {"type": "STRING", "required": True},
        "name": {"type": "STRING", "required": True},
    }
})
assert result.lifecycle == "DRAFT"

# DRAFT 状态下可以自由修改
client.schema.add_property("Equipment", {
    "status": {"type": "ENUM", "enumValues": ["RUNNING", "STOPPED"]}
})

client.schema.remove_property("Equipment", "name")  # 可以删除
client.schema.add_property("Equipment", {
    "displayName": {"type": "STRING", "required": True}  # 重新添加
})

#2.2 ACTIVE — 激活状态

Code
┌──────────────────────────────────────┐
│              ACTIVE                   │
│                                      │
│  特性:                               │
│  ├── 平台自动生成 CRUD API            │
│  ├── 自动创建物理存储(Doris 表等)    │
│  ├── 可以被其他类型引用               │
│  ├── 只允许兼容性变更                  │
│  ├── 可以创建/查询实例数据             │
│  └── 版本号自动递增                   │
│                                      │
│  允许的变更(兼容):                   │
│  ├── 添加可选属性                     │
│  ├── 增加 ENUM 枚举值                │
│  ├── 放宽约束(增大 maxLength)       │
│  ├── 添加索引                        │
│  ├── 修改 displayName / description  │
│  └── 添加新的 InterfaceType 实现      │
│                                      │
│  禁止的变更(破坏性):                 │
│  ├── 删除属性                        │
│  ├── 修改属性类型                     │
│  ├── 修改主键                        │
│  ├── 添加必填属性(无默认值)          │
│  ├── 删除 ENUM 枚举值               │
│  ├── 收紧约束(缩小 maxLength)       │
│  └── 修改关系的基数                   │
│                                      │
│  可用操作:                            │
│  ├── compatibleChange (兼容变更)      │
│  ├── deprecate → 转为 DEPRECATED     │
│  └── 破坏性变更需要通过 Proposal 流程  │
└──────────────────────────────────────┘
Python
# 发布到 ACTIVE
client.schema.publish_object_type("Equipment")

# 兼容性变更 — 成功
client.schema.add_property("Equipment", {
    "description": {"type": "STRING"}  # 可选属性,OK
})

# 兼容性变更 — 增加枚举值,OK
client.schema.add_enum_value("Equipment", "status", "MAINTENANCE")

# 破坏性变更 — 会被拒绝!
try:
    client.schema.remove_property("Equipment", "displayName")
except IncompatibleChangeError as e:
    print(f"拒绝: {e}")
    # 拒绝: Cannot remove required property 'displayName' from ACTIVE ObjectType.
    # Use a Proposal to schedule this breaking change.

#2.3 DEPRECATED — 弃用状态

Code
┌──────────────────────────────────────┐
│            DEPRECATED                 │
│                                      │
│  特性:                               │
│  ├── API 仍然可用(但返回警告头)      │
│  ├── 实例数据仍然可读写               │
│  ├── 新代码不应该再引用此类型          │
│  ├── 平台生成弃用通知                 │
│  ├── 可以设置 sunsetDate(日落日期)  │
│  └── 到期后自动转为 ARCHIVED          │
│                                      │
│  进入条件:                            │
│  ├── 必须从 ACTIVE 状态转入           │
│  ├── 必须指定替代方案或迁移指引        │
│  └── 必须通知所有已知消费者            │
│                                      │
│  可用操作:                            │
│  ├── reactivate → 回到 ACTIVE        │
│  ├── archive    → 转为 ARCHIVED      │
│  └── 有限的兼容性变更(仅 bug fix)    │
└──────────────────────────────────────┘
Python
# 弃用
client.schema.deprecate_object_type(
    name="Equipment",
    reason="Replaced by EquipmentV2 with better property design",
    replacement="EquipmentV2",
    sunset_date="2026-06-01",
    migration_guide="See docs/migration/equipment-v2.md"
)

# API 响应会包含弃用警告
# HTTP/1.1 200 OK
# Deprecation: true
# Sunset: Sat, 01 Jun 2026 00:00:00 GMT
# Link: <docs/migration/equipment-v2.md>; rel="successor-version"

# 可以反悔——回到 ACTIVE
client.schema.reactivate_object_type("Equipment")

#2.4 ARCHIVED — 归档状态

Code
┌──────────────────────────────────────┐
│             ARCHIVED                  │
│                                      │
│  特性:                               │
│  ├── API 不再可用(返回 410 Gone)    │
│  ├── 实例数据已迁移或删除             │
│  ├── Schema 定义保留(审计用)         │
│  ├── 不可修改、不可回退               │
│  └── 保留在 SchemaRegistry 历史中     │
│                                      │
│  进入条件:                            │
│  ├── 必须从 DEPRECATED 状态转入       │
│  ├── 所有实例数据必须已清零或迁移      │
│  ├── 所有依赖此类型的 RelationType     │
│  │   必须已删除或重定向               │
│  └── 所有依赖此类型的 ActionType       │
│      必须已删除或重定向               │
│                                      │
│  不可执行任何修改操作                  │
└──────────────────────────────────────┘
Python
# 归档(需要满足所有前置条件)
try:
    client.schema.archive_object_type("Equipment")
except ArchivePreConditionError as e:
    print(f"前置条件不满足: {e}")
    # 前置条件不满足:
    #   - 3 active relations reference 'Equipment'
    #   - 127 instances still exist
    #   - 2 ActionTypes target 'Equipment'

# 先清理依赖
client.schema.delete_relation_type("EquipmentBelongsToLine")
client.data.migrate_instances("Equipment", "EquipmentV2", mapping={...})
client.schema.delete_action_type("ScheduleMaintenance")

# 再次归档
client.schema.archive_object_type("Equipment")  # 成功

#3. 状态转换完整图

Code
                    ┌──────────┐
                    │  CREATE   │
                    └────┬─────┘
                         │
                         ▼
              ┌──────────────────┐
              │      DRAFT       │◄──────────────────────┐
              │                  │                       │
              │  自由修改         │          clone()      │
              │  无 API          │     (从任何状态克隆)    │
              │  无存储          │                       │
              └────┬────────┬───┘                       │
                   │        │                           │
              publish    delete                         │
                   │        │                           │
                   ▼        ▼                           │
         ┌─────────────┐  (永久删除)                     │
         │   ACTIVE     │                               │
         │              │                               │
         │  API 可用     │ ◄─── reactivate ────┐        │
         │  存储已创建    │                      │        │
         │  兼容变更 only │                      │        │
         └────┬─────────┘                      │        │
              │                                │        │
          deprecate                            │        │
              │                                │        │
              ▼                                │        │
    ┌──────────────────┐                       │        │
    │   DEPRECATED      │──────────────────────┘        │
    │                   │                               │
    │  API 带警告       │                               │
    │  通知消费者       │  ──── clone("EquipmentV3") ───┘
    │  有日落日期       │
    └────┬──────────────┘
         │
      archive
         │
         ▼
    ┌──────────────────┐
    │    ARCHIVED       │
    │                   │
    │  API 返回 410     │
    │  只读历史         │
    │  不可回退         │
    └──────────────────┘

#4. 兼容性验证引擎

#4.1 变更类型分类

Code
┌─────────────────────────────────────────────────┐
│            变更类型分类矩阵                       │
├─────────────────────┬───────────┬───────────────┤
│ 变更操作             │ 兼容性     │ ACTIVE 下允许  │
├─────────────────────┼───────────┼───────────────┤
│ 添加可选属性         │ 兼容 ✅    │ 是            │
│ 添加有默认值的必填属性│ 兼容 ✅    │ 是            │
│ 添加 ENUM 枚举值     │ 兼容 ✅    │ 是            │
│ 放宽 maxLength       │ 兼容 ✅    │ 是            │
│ 添加索引             │ 兼容 ✅    │ 是            │
│ 修改 displayName     │ 兼容 ✅    │ 是            │
│ 添加接口实现         │ 兼容 ✅    │ 是            │
├─────────────────────┼───────────┼───────────────┤
│ 删除可选属性         │ 破坏 ❌    │ 需 Proposal   │
│ 删除必填属性         │ 破坏 ❌    │ 需 Proposal   │
│ 修改属性类型         │ 破坏 ❌    │ 需 Proposal   │
│ 修改主键             │ 破坏 ❌    │ 需 Proposal   │
│ 添加无默认值的必填属性│ 破坏 ❌    │ 需 Proposal   │
│ 删除 ENUM 枚举值     │ 破坏 ❌    │ 需 Proposal   │
│ 收紧约束             │ 破坏 ❌    │ 需 Proposal   │
│ 修改关系基数         │ 破坏 ❌    │ 需 Proposal   │
│ 删除接口实现         │ 破坏 ❌    │ 需 Proposal   │
└─────────────────────┴───────────┴───────────────┘

#4.2 兼容性检查流程

Code
                    ┌───────────────┐
                    │  变更请求      │
                    └───────┬───────┘
                            │
                    ┌───────▼───────┐
                    │ 当前状态检查    │
                    └───────┬───────┘
                            │
              ┌─────────────┼─────────────┐
              │             │             │
         DRAFT          ACTIVE       DEPRECATED
              │             │             │
         直接应用     ┌──────▼──────┐   仅 bug fix
                      │ 兼容性分析   │
                      └──────┬──────┘
                             │
                   ┌─────────┼─────────┐
                   │                   │
              兼容变更              破坏性变更
                   │                   │
              直接应用          ┌───────▼───────┐
                              │  Proposal 流程  │
                              │                │
                              │  1. 创建 Proposal│
                              │  2. 影响分析     │
                              │  3. 审核         │
                              │  4. 执行         │
                              └────────────────┘

#4.3 影响分析报告

Python
# 分析破坏性变更的影响
impact = client.schema.analyze_impact(
    object_type="Equipment",
    change={
        "type": "REMOVE_PROPERTY",
        "property": "status"
    }
)

print(impact.report())
# Impact Analysis Report
# ═══════════════════════════════════════════
# Change: Remove property 'status' from Equipment
# Severity: BREAKING
#
# Affected Components:
# ┌──────────────────────────────────────────┐
# │ Component          │ Count │ Severity    │
# ├────────────────────┼───────┼─────────────┤
# │ RelationTypes      │   0   │ -           │
# │ ActionTypes        │   2   │ HIGH        │
# │   - ScheduleMaint  │       │ Uses status │
# │   - TransferEquip  │       │ Uses status │
# │ Derived Props      │   1   │ HIGH        │
# │   - isOperational  │       │ Depends on  │
# │ Metrics            │   1   │ MEDIUM      │
# │   - StatusDistrib  │       │ Groups by   │
# │ API Consumers      │   5   │ HIGH        │
# │ Dashboard Widgets  │   3   │ MEDIUM      │
# └──────────────────────────────────────────┘
#
# Recommendation: Create a Proposal with migration plan

#5. 版本管理

#5.1 语义化版本号

Code
版本号格式:MAJOR.MINOR.PATCH

MAJOR:破坏性变更(需要 Proposal)
MINOR:兼容性新增(新属性、新枚举值)
PATCH:元数据修改(displayName、description)

Equipment v1.0.0 → v1.1.0(添加可选属性 description)
Equipment v1.1.0 → v1.2.0(添加 ENUM 值 MAINTENANCE)
Equipment v1.2.0 → v2.0.0(通过 Proposal 删除属性 oldField)

#5.2 版本历史查询

Python
# 查看版本历史
history = client.schema.get_version_history("Equipment")

for version in history:
    print(f"v{version.number} | {version.timestamp} | "
          f"{version.change_type} | {version.author}")

# v1.0.0 | 2026-01-15 | CREATED     | admin
# v1.1.0 | 2026-01-20 | ADD_PROP    | dev-team
# v1.2.0 | 2026-02-01 | ADD_ENUM    | dev-team
# v2.0.0 | 2026-03-01 | BREAKING    | architect (Proposal #42)

# 查看特定版本的 Schema
schema_v1 = client.schema.get_object_type("Equipment", version="1.0.0")

#5.3 版本对比

Python
diff = client.schema.diff_versions("Equipment", "1.0.0", "2.0.0")

print(diff.summary())
# Schema Diff: Equipment v1.0.0 → v2.0.0
# ════════════════════════════════════════
# Added Properties:
#   + description: STRING (optional)
#   + maintenanceDate: TIMESTAMP (optional)
#
# Modified Properties:
#   ~ status: ENUM added value 'MAINTENANCE'
#
# Removed Properties:
#   - oldField: STRING (was optional)
#
# Compatibility: BREAKING (removed property)

#6. 安全删除协议

#6.1 依赖图分析

Code
被删除的 ObjectType: Equipment

依赖图:
                    ┌──────────────┐
                    │  Equipment   │ ← 要删除这个
                    └──────┬───────┘
                           │
           ┌───────────────┼───────────────┐
           │               │               │
     ┌─────▼─────┐  ┌─────▼─────┐  ┌─────▼─────┐
     │ Relations  │  │ Actions   │  │ Derived   │
     │            │  │           │  │ Props     │
     │ BelongsTo  │  │ Schedule  │  │ OEE       │
     │ Line (3)   │  │ Maint.(2) │  │ Metrics(1)│
     └────────────┘  └───────────┘  └───────────┘
           │
     ┌─────▼──────┐
     │ ProductLine │
     │ (反向引用)   │
     └────────────┘

安全删除需要先清理所有依赖节点

#6.2 Dry-Run 预检

Python
# dry-run 模式:只检查不执行
result = client.schema.delete_object_type(
    "Equipment",
    mode="DRY_RUN"
)

if result.can_delete:
    print("可以安全删除")
else:
    print(f"无法删除,原因:")
    for blocker in result.blockers:
        print(f"  - {blocker.type}: {blocker.name} ({blocker.reason})")

# 无法删除,原因:
#   - RELATION: EquipmentBelongsToLine (references Equipment as source)
#   - RELATION: LineContainsEquipment (references Equipment as target)
#   - ACTION: ScheduleMaintenance (targets Equipment)
#   - ACTION: TransferEquipment (targets Equipment)
#   - DERIVED_PROP: Equipment.oee (depends on Equipment properties)
#   - METRIC: EquipmentOEE (aggregates Equipment.oee)
#   - INSTANCES: 1,247 instances exist

#6.3 级联删除

Python
# 强制删除(级联清理所有依赖)
result = client.schema.delete_object_type(
    "Equipment",
    mode="CASCADE",
    confirm=True,          # 需要显式确认
    backup=True            # 删前备份 Schema 定义
)

# 执行顺序:
# 1. 备份 Schema 定义 → schema-backups/Equipment-v2.0.0.json
# 2. 删除依赖的 Metrics
# 3. 删除依赖的 ActionTypes
# 4. 删除依赖的 Derived Properties
# 5. 删除依赖的 RelationTypes
# 6. 迁移/删除实例数据
# 7. 删除物理存储(Doris 表)
# 8. 从 SchemaRegistry 移除

#7. 多环境生命周期管理

Code
┌─────────────────────────────────────────────────────────┐
│                    Environment Promotion                 │
│                                                         │
│  DEV          STAGING        PRODUCTION                 │
│  ┌────────┐  ┌────────┐    ┌────────┐                  │
│  │ DRAFT  │  │        │    │        │                  │
│  │   ↓    │  │        │    │        │                  │
│  │ ACTIVE │──promote──│ ACTIVE │──promote──│ ACTIVE │  │
│  │        │  │   ↓    │    │        │                  │
│  │        │  │ test   │    │        │                  │
│  └────────┘  └────────┘    └────────┘                  │
│                                                         │
│  每个环境独立的生命周期状态                                │
│  promote 操作会复制 Schema + 运行兼容性检查               │
└─────────────────────────────────────────────────────────┘
Python
# 从 DEV 提升到 STAGING
client.schema.promote(
    object_type="Equipment",
    from_env="dev",
    to_env="staging",
    version="2.0.0"
)

# 从 STAGING 提升到 PRODUCTION
client.schema.promote(
    object_type="Equipment",
    from_env="staging",
    to_env="production",
    version="2.0.0",
    require_approval=True,        # 需要审批
    approvers=["architect-team"]
)

#8. 生命周期事件与钩子

Python
# 注册生命周期事件监听器
@client.schema.on_lifecycle_change("Equipment")
def on_equipment_lifecycle(event):
    """
    event.object_type: "Equipment"
    event.old_state: "ACTIVE"
    event.new_state: "DEPRECATED"
    event.reason: "Replaced by EquipmentV2"
    event.actor: "architect@company.com"
    event.timestamp: "2026-03-01T10:00:00Z"
    """
    if event.new_state == "DEPRECATED":
        # 通知所有消费团队
        notify_consumers(event.object_type, event.reason)
        # 创建 JIRA ticket 跟踪迁移
        create_migration_ticket(event)

    elif event.new_state == "ARCHIVED":
        # 清理相关资源
        cleanup_resources(event.object_type)

# 注册 pre-hook(可以阻止状态转换)
@client.schema.before_lifecycle_change("Equipment")
def before_equipment_change(event):
    if event.new_state == "ARCHIVED":
        # 检查是否还有活跃的 API 调用
        if get_api_call_count(event.object_type, last_days=30) > 0:
            raise BlockTransitionError(
                "Cannot archive: still has API calls in the last 30 days"
            )

#9. 生命周期管理最佳实践

#9.1 Schema 演进策略

Code
策略一:就地修改(In-Place Evolution)
适用于:兼容性变更
┌──────────────┐         ┌──────────────┐
│ Equipment    │         │ Equipment    │
│ v1.0.0       │  ──►   │ v1.1.0       │
│ ACTIVE       │         │ ACTIVE       │
│              │         │ +description │
└──────────────┘         └──────────────┘

策略二:并行版本(Side-by-Side)
适用于:破坏性变更,需要迁移时间
┌──────────────┐         ┌──────────────┐
│ Equipment    │         │ EquipmentV2  │
│ v2.0.0       │         │ v1.0.0       │
│ DEPRECATED   │  ──►   │ ACTIVE       │
│ sunset: 6/1  │         │ (新设计)      │
└──────────────┘         └──────────────┘
两个版本并行运行,直到旧版本日落

策略三:克隆演进(Clone and Evolve)
适用于:大规模重构
┌──────────────┐    clone    ┌──────────────┐
│ Equipment    │ ──────────► │ EquipmentV3  │
│ ACTIVE       │             │ DRAFT        │
└──────────────┘             └──────┬───────┘
                                    │ 修改
                                    ▼
                             ┌──────────────┐
                             │ EquipmentV3  │
                             │ ACTIVE       │
                             └──────────────┘

#9.2 检查清单

Code
□ DRAFT → ACTIVE 前检查:
  ├── □ 有且仅有一个主键属性
  ├── □ 至少有一个非主键属性
  ├── □ 所有必填属性有合理的默认值或业务来源
  ├── □ 所有 REFERENCE 属性指向已存在的 ObjectType
  ├── □ 所有 StructType 引用已注册
  ├── □ 所有 InterfaceType 的必需属性已实现
  └── □ 命名符合 camelCase 规范

□ ACTIVE → DEPRECATED 前检查:
  ├── □ 指定了替代方案或迁移指引
  ├── □ 设置了合理的日落日期(至少 30 天后)
  ├── □ 通知了所有已知消费团队
  └── □ 创建了迁移计划

□ DEPRECATED → ARCHIVED 前检查:
  ├── □ 所有实例数据已迁移或删除
  ├── □ 所有依赖关系已清理
  ├── □ 所有 ActionType 已重定向或删除
  ├── □ 最近 30 天无 API 调用
  └── □ 已备份 Schema 定义

#10. 常见问题解答

#Q1:ACTIVE 状态下必须做破坏性变更怎么办?

使用 Proposal 流程(详见 S4-09):

Python
proposal = client.schema.create_proposal(
    title="Remove deprecated field 'oldStatus' from Equipment",
    changes=[
        {"type": "REMOVE_PROPERTY", "objectType": "Equipment", "property": "oldStatus"}
    ],
    migration_plan="Step 1: Update all consumers to use 'status' instead...",
    rollback_plan="Re-add 'oldStatus' as optional with data backfill"
)

# 提交审核
proposal.submit_for_review(reviewers=["architect-team"])

# 审核通过后执行
proposal.execute()  # 自动执行变更 + 版本号升级为 MAJOR

#Q2:Schema 修改后如何通知消费者?

Python
# 查询所有消费者
consumers = client.schema.get_consumers("Equipment")

for consumer in consumers:
    print(f"{consumer.type}: {consumer.name} (last access: {consumer.last_access})")

# SDK_CLIENT: frontend-app (last access: 2 min ago)
# SDK_CLIENT: data-pipeline (last access: 1 hour ago)
# DASHBOARD: equipment-monitor (last access: 5 min ago)
# ACTION: ScheduleMaintenance (always active)

# 自动通知
client.schema.notify_consumers(
    "Equipment",
    message="Property 'oldStatus' will be removed on 2026-06-01. "
            "Please migrate to 'status'.",
    channel=["email", "webhook"]
)

#Q3:误操作把 ACTIVE 改成 DEPRECATED 怎么办?

Python
# 在日落日期前可以回退
client.schema.reactivate_object_type("Equipment")
# 状态回到 ACTIVE,API 恢复正常,弃用警告移除

#Key Takeaways

  1. 四阶段生命周期是 Schema 安全演进的保障。DRAFT 允许自由实验,ACTIVE 限制为兼容变更,DEPRECATED 给消费者迁移时间,ARCHIVED 保留历史审计记录。这比"ALTER TABLE + 祈祷"安全 100 倍。

  2. 兼容性验证引擎是自动的守门员。每次对 ACTIVE 类型的变更都经过兼容性检查,破坏性变更必须走 Proposal 流程——这消除了"开发改了 Schema 但忘了通知前端"的经典灾难。

  3. 安全删除协议防止悬挂引用。通过 dry-run 预检和依赖图分析,确保删除操作不会留下断裂的关系链。即使使用级联删除,也会先备份 Schema 定义。

#下一篇

S4-04: RelationType 与知识图谱:如何用关系连接业务世界 —— 我们将深入 RelationType 的关系建模、多跳遍历和图布局。

tags: object-type, lifecycle, state-machine, schema-evolution, compatibility, versioning, coomia-dip, deprecation