关于 content-distribution
面向开发 AEM Cloud Service 发布与分发工作流的 beta 技能集合。它根据任务提供 Replication API 或 Sling Distribution 事件方面的指导,涵盖内容发布和生命周期监控。
主要功能
- 01按任务分流发布与监控指南
- 02提供 Replication API 指引
- 03提供 Sling Distribution 事件指引
- 04涵盖生命周期事件和故障处理
适用场景
- 01以编程方式发布或取消发布内容
- 02监控分发进度与故障
- 03将发布操作加入工作流步骤
- 04将内容发布到 Preview 以供审核
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ adobe/ skills --skill content-distribution安装后在 Claude Code 中输入/content-distribution确认已加载。
附带文件README.mdreplication/references/patterns.md
详细介绍
AEM Cloud Service 内容分发
Beta 技能:此技能目前处于 Beta 阶段,正在积极开发中。 在生产环境中使用前,请仔细检查结果。 请在 https://github.com/adobe/skills/issues 报告问题
使用官方 AEM Cloud Service API,以编程方式发布内容并监控分发情况。
何时使用此技能
在以下场景中使用此技能集合:
- 以编程方式发布:通过
ReplicatorAPI 发布内容 - 分发监控:跟踪分发生命周期事件
- 自动化工作流:与工作流流程步骤集成
- 事件处理:响应分发事件(失败、完成)
- 自定义发布逻辑:批量操作、发布到 Preview 层
子技能
这是一个父技能,会根据任务将请求路由到专用子技能:
| 任务 | 子技能 | 文件 |
|---|---|---|
| 以编程方式发布或取消发布内容 | Replication API | replication/SKILL.md |
| 监控分发事件和生命周期 | Sling Distribution Events | sling-distribution/SKILL.md |
快速选择指南
需要以下功能时,选择 Replication API:
- 从自定义 OSGi 服务发布内容
- 将发布功能集成到工作流步骤中
- 执行批量发布操作
- 发布到 Preview 层以供审核
- 以编程方式检查复制状态
需要以下功能时,选择 Sling Distribution Events:
- 监控分发生命周期(已创建、已排队、已分发、已导入)
- 响应分发失败
- 触发分发后的操作(缓存预热、通知)
- 审核分发操作
- 跟踪分发指标
官方 API
这两项技能均使用官方支持的 AEM Cloud Service API:
-
Replication API:
com.day.cq.replication- Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/com/day/cq/replication/package-summary.html
- 主要类:
Replicator、ReplicationOptions、ReplicationStatus、ReplicationActionType
-
Sling Distribution API:
org.apache.sling.distribution- Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/org/apache/sling/distribution/package-summary.html
- 主要包:
org.apache.sling.distribution.event(事件主题和属性)
架构概览
┌──────────────────────────────────────────────────┐
│ Replication API (Your Code) │
│ com.day.cq.replication.Replicator │
│ │
│ replicator.replicate(session, ACTIVATE, path) │
└────────────────────┬─────────────────────────────┘
↓
┌──────────────────────────────────────────────────┐
│ Sling Distribution (Underlying Transport) │
│ org.apache.sling.distribution │
│ │
│ [AGENT_PACKAGE_CREATED] ← Distribution events │
│ ↓ fire at each stage │
│ [AGENT_PACKAGE_QUEUED] │
│ ↓ │
│ [AGENT_PACKAGE_DISTRIBUTED] │
│ ↓ │
│ Adobe Developer Pipeline Service │
│ ↓ │
│ [IMPORTER_PACKAGE_IMPORTED] │
└──────────────────────────────────────────────────┘
↓
Content live on Publish/Preview
工作原理
- 你的代码调用
Replicator.replicate()发布内容 - Sling Distribution 打包内容并触发
AGENT_PACKAGE_CREATED事件 - 包被排队,并触发
AGENT_PACKAGE_QUEUED事件 - 包被发送到 Adobe Developer 管道,并触发
AGENT_PACKAGE_DISTRIBUTED事件 - 目标层导入内容,并触发
IMPORTER_PACKAGE_IMPORTED事件 - 内容在目标层(Publish 或 Preview)上线
常见模式
模式 1:发布并监控
发布内容并跟踪其上线时间:
// Step 1: Publish using Replication API
@Reference
private Replicator replicator;
public void publishContent(Session session, String path) throws ReplicationException {
replicator.replicate(session, ReplicationActionType.ACTIVATE, path);
}
// Step 2: Monitor completion using Distribution Events
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.IMPORTER_PACKAGE_IMPORTED
})
public class PublishCompletionHandler implements EventHandler {
@Override
public void handleEvent(Event event) {
String[] paths = (String[]) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PATHS
);
LOG.info("Content is now live: {}", String.join(",", paths));
// Trigger post-publish actions (cache warming, notifications, etc.)
}
}
模式 2:Preview 优先工作流
先发布到 Preview 以供审批,然后发布到 Publish:
// Workflow Step 1: Publish to Preview
public void publishToPreview(Session session, String path) throws ReplicationException {
ReplicationOptions options = new ReplicationOptions();
options.setFilter(agent -> "preview".equals(agent.getId()));
replicator.replicate(session, ReplicationActionType.ACTIVATE, path, options);
}
// Workflow Step 2: After approval, publish to Publish tier
public void publishToProduction(Session session, String path) throws ReplicationException {
ReplicationOptions options = new ReplicationOptions();
options.setFilter(agent -> "publish".equals(agent.getId()));
replicator.replicate(session, ReplicationActionType.ACTIVATE, path, options);
}
模式 3:自动发布并处理失败
自动发布内容,并在失败时发出提醒:
// Publish handler
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
SlingConstants.TOPIC_RESOURCE_CHANGED
})
public class AutoPublishHandler implements EventHandler {
@Reference
private Replicator replicator;
@Override
public void handleEvent(Event event) {
String path = (String) event.getProperty(SlingConstants.PROPERTY_PATH);
if (shouldAutoPublish(path)) {
try (ResourceResolver resolver = getServiceResolver()) {
Session session = resolver.adaptTo(Session.class);
replicator.replicate(session, ReplicationActionType.ACTIVATE, path);
} catch (Exception e) {
LOG.error("Auto-publish failed", e);
}
}
}
}
// Failure monitoring
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_DROPPED
})
public class FailureAlertHandler implements EventHandler {
@Reference
private AlertService alertService;
@Override
public void handleEvent(Event event) {
String packageId = (String) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PACKAGE_ID
);
alertService.sendAlert("Distribution failed", packageId);
}
}
速率限制和约束
| 约束 | 限制 | 影响 |
|---|---|---|
| 每次 API 调用的路径数(建议值) | 100 | 提供事务保证;超过此数量时系统会自动拆分 |
| 负载大小 | 10 MB | 不包括二进制文件 |
注意:根据 Cloud Service Javadoc,
ReplicationOptions.setUseAtomicCalls()已标记为@Deprecated/“不再需要”——对于超过 100 个路径的请求,系统会自动分桶处理。
最佳实践:对于大型分层内容树,请使用 Tree Activation 工作流步骤,而不是自定义代码。
与 AEM 6.x 的主要区别
| 功能 | AEM 6.x | AEM Cloud Service |
|---|---|---|
| 复制 API | com.day.cq.replication.Replicator | ✅ 相同的 API |
| 复制代理 | 手动配置 | ✅ 自动配置(由 Adobe 管理) |
| 传输机制 | 直接 JCR 复制 | ✅ 通过 Adobe 管道进行 Sling Distribution |
| 预览层 | 不可用 | ✅ 可用(需要代理过滤) |
| 分发事件 | 有限 | ✅ 通过 org.apache.sling.distribution.event 提供完整生命周期事件 |
| 代理配置 | 手动 OSGi 配置 | ❌ 不公开(由 Adobe 管理) |
不要使用这些技能的情况
以下情况请改用 UI 工作流:
- 手动发布少量内容
- 一次性发布操作
- 内容作者可以使用快速发布或管理发布
以下情况请使用树激活工作流:
- 发布大型分层内容树
- 对数百个路径执行批量操作,且不需要自定义逻辑
快速参考
复制 API 基础知识
// Inject service
@Reference
private Replicator replicator;
// Publish single page
replicator.replicate(session, ReplicationActionType.ACTIVATE, "/content/mysite/page");
// Unpublish
replicator.replicate(session, ReplicationActionType.DEACTIVATE, "/content/mysite/page");
// Bulk publish (≤100 for transactional guarantee)
replicator.replicate(session, ReplicationActionType.ACTIVATE,
new String[]{"/content/page1", "/content/page2"}, null);
// Publish to Preview
ReplicationOptions options = new ReplicationOptions();
options.setFilter(agent -> "preview".equals(agent.getId()));
replicator.replicate(session, ReplicationActionType.ACTIVATE, "/content/page", options);
// Check status
ReplicationStatus status = replicator.getReplicationStatus(session, "/content/page");
boolean isPublished = status != null && status.isActivated();
Distribution 事件处理基础知识
// Listen for distribution events
@Component(service = EventHandler.class, property = {
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_CREATED,
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_DISTRIBUTED,
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.AGENT_PACKAGE_DROPPED,
org.osgi.service.event.EventConstants.EVENT_TOPIC + "=" +
DistributionEventTopics.IMPORTER_PACKAGE_IMPORTED
})
public class DistributionMonitor implements EventHandler {
@Override
public void handleEvent(Event event) {
String topic = event.getTopic();
String packageId = (String) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PACKAGE_ID
);
String[] paths = (String[]) event.getProperty(
DistributionEventProperties.DISTRIBUTION_PATHS
);
// Handle event based on topic
if (DistributionEventTopics.AGENT_PACKAGE_DROPPED.equals(topic)) {
LOG.error("Distribution failed: {}", packageId);
} else if (DistributionEventTopics.IMPORTER_PACKAGE_IMPORTED.equals(topic)) {
LOG.info("Content is live: {}", String.join(",", paths));
}
}
}
最佳实践
- 使用正确的 API:使用复制 API 进行发布,使用 Distribution 事件进行监控
- 遵守速率限制:事务保证最多支持 100 个路径
- 处理故障:始终捕获
ReplicationException,监控AGENT_PACKAGE_DROPPED事件 - 使用服务用户:切勿使用管理员凭据
- 适当地过滤事件:只监听所需的事件
- 验证权限:复制前调用
replicator.checkPermission() - 仅发布所需内容:避免不必要的批量操作
故障排除
复制问题
| 问题 | 解决方案 |
|---|---|
ReplicationException | 检查服务用户是否具有 crx:replicate 权限 |
| 目标层上没有内容 | 验证代理过滤器,并检查复制状态 |
| “路径过多”错误 | 为确保事务保证,请使用不超过 100 个路径;也可传入所有路径,系统会自动拆分 |
事件处理问题
| 问题 | 解决方案 |
|---|---|
| 事件处理程序未触发 | 确认事件主题常量完全匹配 |
| 缺少事件属性 | 始终对事件属性进行空值检查 |
| 处理程序拖慢分发速度 | 使用异步作业处理,不要阻塞 |
详细文档
如需详细示例、代码示例和高级用法,请参阅:
- 复制 API:参见 replication/SKILL.md
- Sling Distribution 事件:参见 sling-distribution/SKILL.md
参考资料
- 复制 Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/com/day/cq/replication/package-summary.html
- Sling Distribution Javadoc:https://developer.adobe.com/experience-manager/reference-materials/cloud-service/javadoc/org/apache/sling/distribution/package-summary.html
- Adobe 文档:https://experienceleague.adobe.com/docs/experience-manager-cloud-service/content/operations/replication.html
- Sling Distribution:https://sling.apache.org/documentation/bundles/content-distribution.html
- 服务用户 / Repo Init:https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/aem-project-content-package-structure#repo-init