mcpField
C
content-distribution

content-distribution

github.com/adobe开发316860 次安装今天更新
代码仓库

关于 content-distribution

面向开发 AEM Cloud Service 发布与分发工作流的 beta 技能集合。它根据任务提供 Replication API 或 Sling Distribution 事件方面的指导,涵盖内容发布和生命周期监控。

主要功能

  1. 01按任务分流发布与监控指南
  2. 02提供 Replication API 指引
  3. 03提供 Sling Distribution 事件指引
  4. 04涵盖生命周期事件和故障处理

适用场景

  1. 01以编程方式发布或取消发布内容
  2. 02监控分发进度与故障
  3. 03将发布操作加入工作流步骤
  4. 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,以编程方式发布内容并监控分发情况。

何时使用此技能

在以下场景中使用此技能集合:

  • 以编程方式发布:通过 Replicator API 发布内容
  • 分发监控:跟踪分发生命周期事件
  • 自动化工作流:与工作流流程步骤集成
  • 事件处理:响应分发事件(失败、完成)
  • 自定义发布逻辑:批量操作、发布到 Preview 层

子技能

这是一个父技能,会根据任务将请求路由到专用子技能:

任务子技能文件
以编程方式发布或取消发布内容Replication APIreplication/SKILL.md
监控分发事件和生命周期Sling Distribution Eventssling-distribution/SKILL.md

快速选择指南

需要以下功能时,选择 Replication API:

  • 从自定义 OSGi 服务发布内容
  • 将发布功能集成到工作流步骤中
  • 执行批量发布操作
  • 发布到 Preview 层以供审核
  • 以编程方式检查复制状态

需要以下功能时,选择 Sling Distribution Events:

  • 监控分发生命周期(已创建、已排队、已分发、已导入)
  • 响应分发失败
  • 触发分发后的操作(缓存预热、通知)
  • 审核分发操作
  • 跟踪分发指标

官方 API

这两项技能均使用官方支持的 AEM Cloud Service API:

  1. Replication API:com.day.cq.replication

  2. Sling Distribution API:org.apache.sling.distribution

架构概览

┌──────────────────────────────────────────────────┐
│ 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
工作原理
  1. 你的代码调用 Replicator.replicate() 发布内容
  2. Sling Distribution 打包内容并触发 AGENT_PACKAGE_CREATED 事件
  3. 包被排队,并触发 AGENT_PACKAGE_QUEUED 事件
  4. 包被发送到 Adobe Developer 管道,并触发 AGENT_PACKAGE_DISTRIBUTED 事件
  5. 目标层导入内容,并触发 IMPORTER_PACKAGE_IMPORTED 事件
  6. 内容在目标层(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.xAEM Cloud Service
复制 APIcom.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));
        }
    }
}

最佳实践

  1. 使用正确的 API:使用复制 API 进行发布,使用 Distribution 事件进行监控
  2. 遵守速率限制:事务保证最多支持 100 个路径
  3. 处理故障:始终捕获 ReplicationException,监控 AGENT_PACKAGE_DROPPED 事件
  4. 使用服务用户:切勿使用管理员凭据
  5. 适当地过滤事件:只监听所需的事件
  6. 验证权限:复制前调用 replicator.checkPermission()
  7. 仅发布所需内容:避免不必要的批量操作

故障排除

复制问题
问题解决方案
ReplicationException检查服务用户是否具有 crx:replicate 权限
目标层上没有内容验证代理过滤器,并检查复制状态
“路径过多”错误为确保事务保证,请使用不超过 100 个路径;也可传入所有路径,系统会自动拆分
事件处理问题
问题解决方案
事件处理程序未触发确认事件主题常量完全匹配
缺少事件属性始终对事件属性进行空值检查
处理程序拖慢分发速度使用异步作业处理,不要阻塞

详细文档

如需详细示例、代码示例和高级用法,请参阅:

参考资料

评论

支持 Markdown