关于 managing-cdc-enablement
为 Salesforce CDC 生成 Metadata API 可用的订阅元数据,适合配置变更事件的开发者。涵盖默认及自定义通道,并处理字段增强和过滤表达式的格式细节。
主要功能
- 01生成 PlatformEventChannelMember 元数据
- 02生成自定义通道元数据
- 03订阅标准或自定义对象
- 04配置增强字段与过滤表达式
- 05遵循 Metadata API 命名格式
适用场景
- 01为对象启用变更数据捕获
- 02将对象订阅到自定义通道
- 03为事件补充查找字段
- 04按条件筛选变更事件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill managing-cdc-enablement安装后在 Claude Code 中输入/managing-cdc-enablement确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/PlatformEventChannel-template.xmlPlatformEventChannelMember-template.xmlreferences/deploy-troubleshooting.mdfilter-expressions.md详细介绍
管理变更数据捕获启用
生成用于订阅 Salesforce 对象以启用变更数据捕获的元数据:用于默认 ChangeEvents 通道或自定义通道的 PlatformEventChannelMember 文件,以及用于新建自定义通道的 PlatformEventChannel 文件。内容涵盖扩展字段、筛选表达式,以及 Metadata API 实际接受的规范命名和取值格式(这些格式与许多内部测试数据和代码搜索结果中出现的取值不同)。
范围
- 范围内:为 CDC 生成
PlatformEventChannelMember和PlatformEventChannel元数据。订阅标准对象、自定义对象或两者。配置扩展字段。配置筛选表达式。定义自定义数据通道。 - 范围外:发布自定义平台事件(PE)——这属于另一种元数据类型(
PlatformEvent)。Pub/Sub API 或外部 Kafka/Bayeux 配置。定价/限制指南——请引导用户参阅 CDC 开发者指南。Apex 中以编程方式实现的事件总线订阅者。
澄清问题
如果尚不明确,生成前请向用户确认:
- 哪个实体(或哪些实体)需要启用 CDC?标准对象、自定义对象,还是两者都有?
- 使用默认通道(
ChangeEvents)还是自定义通道?如果是自定义通道,其标签是什么? - 是否需要扩展字段?(即使未发生变化,消费者仍需要获取的查找 ID。)
- 是否需要筛选表达式?(用于控制哪些变更事件发出的 SOQL-WHERE 子句正文。)
必需输入
继续操作前,请收集或推断以下信息:
- 源实体 API 名称——例如
Account、Lead、Order__c。此技能会在内部将其转换为变更事件实体名称(参见工作流第 2 步)。 - 通道——
ChangeEvents(默认值)或以__chn结尾的自定义通道开发者名称。 - 扩展字段(可选)——源对象上应在每个变更事件中包含其值的字段 API 名称列表。
- 筛选表达式(可选)——针对变更事件有效负载中字段的谓词(例如
Status__c != null)。
除非另有说明,否则默认值如下:
- 通道:
ChangeEvents(默认 CDC 通道——无需路径前缀)。 - 扩展字段:无。
- 筛选表达式:无。
如果用户的请求明确且完整,请立即生成,不要进行不必要的来回确认。
工作流
所有步骤均按顺序执行。请勿跳过或调整顺序。
在生成任何内容之前,必须明确 CDC 仅有以下有效元数据类型: CDC 完全通过 PlatformEventChannelMember(每个订阅实体一个)和 PlatformEventChannel(仅用于自定义通道)来表示。请勿使用 <ChangeDataCapture>、.changeDataCapture-meta.xml、changeDataCapture/ 目录、EnableChangeDataCapture 或 ManagedEventSubscription——这些均不属于 CDC 范围。如果发现自己正在编写其中任何一种内容,请停下,改用 PlatformEventChannelMember 文件。
-
确定通道——如果用户指定了自定义通道,请生成
PlatformEventChannel文件(参见第 4 步)。否则,默认通道使用字面值ChangeEvents。 -
将源实体转换为 ChangeEvent 实体名称——
<selectedEntity>是 ChangeEvent 类型,不是源对象:源对象 <selectedEntity>的值AccountAccountChangeEventLeadLeadChangeEventContactContactChangeEventOrder__c(自定义)Order__ChangeEventMyThing__c(自定义)MyThing__ChangeEvent对于标准对象:追加
ChangeEvent。对于自定义对象:将末尾的__c替换为__ChangeEvent(保留双下划线)。 -
生成频道成员文件 — 每个
(实体, 频道)对应一个文件。文件名和 fullName 始终在实体名称主体与ChangeEvent之间使用一个下划线 — 无论 XML 正文中的selectedEntity如何格式化。对于自定义对象,生成文件名时从源名称中去掉__c:源对象 文件名(及 fullName) <selectedEntity>(位于 XML 中)AccountAccount_ChangeEvent.platformEventChannelMember-meta.xmlAccountChangeEventLeadLead_ChangeEvent.platformEventChannelMember-meta.xmlLeadChangeEventOrder__cOrder_ChangeEvent.platformEventChannelMember-meta.xml(而非Order__ChangeEvent)Order__ChangeEventMyThing__cMyThing_ChangeEvent.platformEventChannelMember-meta.xml(而非MyThing__ChangeEvent)MyThing__ChangeEvent自定义对象的情况最容易出错 — 文件名使用一个下划线,而
selectedEntity保留两个下划线。请将assets/PlatformEventChannelMember-template.xml作为结构模板阅读。 -
对于自定义频道,生成一个
PlatformEventChannel文件 — 如果任何成员引用非默认频道,则此文件为必需。根据用户提供的标签生成 DeveloperName:去掉空格和非字母数字字符,转换为 CamelCase,然后始终追加字面后缀__chn。文件名和频道的<eventChannel>引用必须使用此准确形式,否则部署会因Invalid channel name失败:用户提供的名称 DeveloperName 文件名 Partner SyncPartnerSync__chnPartnerSync__chn.platformEventChannel-meta.xml(而非Partner_Sync...或PartnerSync...)Order UpdatesOrderUpdates__chnOrderUpdates__chn.platformEventChannel-meta.xmldata syncDataSync__chnDataSync__chn.platformEventChannel-meta.xml此频道上的成员使用相同的 DeveloperName 引用它:
<eventChannel>PartnerSync__chn</eventChannel>。请阅读assets/PlatformEventChannel-template.xml。 -
按需添加丰富化字段 — 每个字段都重复
<enrichedFields><name>FIELD_API_NAME</name></enrichedFields>块。名称必须是源实体上的单跳 API 名称 — 已验证可用的包括:标准查找 ID(OwnerId、ParentId)、自定义查找字段(MyLookup__c)和自定义非关系字段(Region__c、Status__c)。部署会拒绝关系遍历,例如Owner.Name或Parent.Account.Industry,并显示错误 “The selected field, X.Y, isn't valid”。 -
按需添加筛选表达式 — 将谓词放入
<filterExpression>...</filterExpression>中。正文是 WHERE 子句正文,不含WHERE关键字(例如Status__c != null,而非WHERE Status__c != null)。支持的运算符、字段类型和注意事项,请阅读references/filter-expressions.md。
规则 / 约束
| 约束 | 原因 |
|---|---|
<selectedEntity> 是 ChangeEvent 类型名称,而不是源对象名称 | Metadata API 会将成员绑定到 ChangeEvent 实体;直接传入 Account 会失败,并提示“invalid event in selectedEntity”。 |
成员的 fullName 使用单下划线:Account_ChangeEvent | 双下划线形式(Account__ChangeEvent)会被解析为 <namespace>__<name>,并遭到拒绝,提示:“Cannot create a new component with the namespace: Account”。 |
默认通道值必须恰好为 ChangeEvents——不带路径前缀 | 较旧的样例和部分文档中会显示 data/ChangeEvents;使用该值部署会返回“Unable to find the specified channel”。 |
| enrichment 字段名称必须是源实体上的单跳 API 名称 | 标准字段(OwnerId)、自定义查找字段(MyLookup__c)和自定义非关系字段(Region__c)都能通过校验。Owner.Name 之类的遍历会遭到拒绝,提示:“The selected field, X.Y, isn't valid”。 |
<filterExpression> 内容中不能包含 WHERE 关键字 | 部署会返回“filter expression has syntax errors: unexpected token: 'WHERE'”。 |
筛选器不能引用 IsDeleted,也不能进行关系遍历(Owner.Username) | 部署会以“field is invalid”拒绝。 |
筛选器中的 DateTime 字段仅支持相等比较(=、!=)——不支持 < / > | 部署会返回“Only equality operators are supported for this field type or value”。请使用具名日期字面值:LastModifiedDate = TODAY。 |
| 筛选器右侧必须是字面值——不能进行字段间比较 | BillingCity = ShippingCity 会返回“unexpected token: 'ShippingCity'”。 |
复合字段(例如 BillingAddress)在筛选器中必须使用带点号的组件访问方式 | BillingAddress.City = 'X' 可以部署;扁平名称 BillingCity 会以“field is invalid”遭到拒绝;直接使用 BillingAddress 会以“has to be used with a component field”遭到拒绝。注意,这与使用扁平名称的 <enrichedFields> 正好相反。 |
自定义通道文件名必须在 meta-xml 后缀前以 __chn 结尾 | 这是 Salesforce 的 MDAPI 命名约定;名称不匹配会导致部署歧义。 |
自定义通道 XML 必须包含 <channelType>data</channelType> | 如果没有 data,该通道会因 CDC 被拒绝(流式传输 / 事件通道还有其他类型)。 |
| 源自定义对象必须已存在(或在同一事务中部署) | Foo__c 不存在时,其 ChangeEvent 实体也不存在;否则成员部署会失败。 |
绝不要为默认的 ChangeEvents 通道生成 PlatformEventChannel 文件 | 默认通道由系统提供。成员通过 <eventChannel>ChangeEvents</eventChannel> 引用它,但只有自定义(__chn)通道需要 channel-meta 文件。 |
PlatformEventChannelMember 仅接受四个元素:<enrichedFields>、<eventChannel>、<filterExpression>、<selectedEntity> | 添加 <description>、<isActive>、<masterLabel> 或任何其他元素都会导致 XML 架构校验失败:“Element {...} invalid at this location”。请仅使用这四个有文档说明的元素。 |
PlatformEventChannel 仅接受两个元素:<channelType> 和 <label> | 添加 <masterLabel>、<description> 等会导致“Element {...}masterLabel invalid at this location in type PlatformEventChannel”。请使用 <label>,而不是 <masterLabel>。 |
仅生成元数据文件——绝不要从此技能运行 sf project deploy start | 此技能负责生成构件;部署属于单独的生命周期环节。 |
常见问题
| 问题 | 解决方法 |
|---|---|
Unable to find the specified channel | 设置 <eventChannel>ChangeEvents</eventChannel>(不要加 data/ 前缀)。 |
The PlatformEventChannelMember can't be created because it references an invalid event in the "selectedEntity" field | 使用 ChangeEvent 名称,而不是源对象:AccountChangeEvent,而非 Account。 |
Cannot create a new component with the namespace: <Object> | 将文件名改为使用单个下划线:Account_ChangeEvent...,而非 Account__ChangeEvent...。 |
The selected field, X.Y, isn't valid(在 <enrichedFields> 中) | 将 Owner.Name 替换为 OwnerId。CDC 会自动丰富查找字段;只有单跳字段 API 名称通过验证。 |
filter expression has syntax errors: unexpected token: 'WHERE' | 移除 WHERE 关键字。主体只能包含谓词。 |
The BillingCity field in the filter expression is invalid(或任何平铺的地址组件) | 使用复合点分形式:BillingAddress.City,而非 BillingCity。完整的复合字段矩阵请参阅 references/filter-expressions.md。 |
| 自定义对象成员报错 "ChangeEvent doesn't exist" | 源对象尚未部署。确保 Foo__c 对象元数据包含在同一次部署中,或已存在于组织中。 |
第二次部署时出现 DUPLICATE_VALUE | 该成员已订阅。请先删除,或跳过;CDC 不支持直接对成员执行 upsert。 |
对 .changeDataCapture-meta.xml 文件出现 sf infra error (TypeInferenceError, DeployMetadata): Could not infer a metadata type | 该文件扩展名和元数据类型不存在。请将 changeDataCapture/<Entity>.changeDataCapture-meta.xml 文件替换为 platformEventChannelMembers/<Entity>_ChangeEvent.platformEventChannelMember-meta.xml 文件。 |
用户说“订阅 Order__c”,但实际指的是标准对象 Order | 请确认:OrderChangeEvent(标准对象)和 Order__ChangeEvent(自定义对象)是不同的实体。 |
输出预期
交付内容:
- 每个已订阅实体对应一个
force-app/.../platformEventChannelMembers/<Entity>_ChangeEvent.platformEventChannelMember-meta.xml。 - 每个自定义通道对应一个
force-app/.../platformEventChannels/<DevName>__chn.platformEventChannel-meta.xml(如果有)。
文件结构遵循 assets/ 中的模板。
收到生成的文件后,用户可以先运行 sf project deploy start --dry-run -d <path> --target-org <alias> 验证,再进行部署。如果 dry-run 出现不熟悉的错误,references/deploy-troubleshooting.md 会将常见部署错误对应到元数据端的修复方法。
跨技能集成
| 需求 | 委托给 |
|---|---|
| 生成源自定义对象 | generating-custom-object 技能 |
| 生成丰富数据或筛选条件引用的自定义字段 | generating-custom-field 技能 |
| 为使用变更事件的用户创建权限集 | generating-permission-set 技能 |
参考文件索引
| 文件 | 阅读时机 |
|---|---|
assets/PlatformEventChannelMember-template.xml | 步骤 3——通道成员的起始结构 |
assets/PlatformEventChannel-template.xml | 步骤 4——自定义通道的起始结构 |
references/filter-expressions.md | 步骤 6——编写筛选表达式时,了解支持的运算符和字段类型矩阵 |
references/deploy-troubleshooting.md | 用户报告 dry-run 部署错误并请求协助诊断时 |