mcpField
C
content-distribution

content-distribution

github.com/adobe開発316860 回インストール今日更新
リポジトリ

content-distribution について

AEM Cloud Service の公開・配信ワークフローを開発するためのベータ版スキル集です。タスクに応じて Replication API または Sling Distribution イベントのガイダンスを示し、公開とライフサイクル監視を扱います。

主な機能

  1. 01公開と監視のタスクを振り分け
  2. 02Replication API のガイダンス
  3. 03Sling 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 コンテンツ配信

ベータ版スキル:このスキルはベータ版で、現在も開発が進められています。 本番環境で使用する前に、結果を慎重に確認してください。 問題は 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
プレビュー層利用不可✅ 利用可能(エージェントのフィルタリングが必要)
Distribution イベント限定的✅ org.apache.sling.distribution.event による完全なライフサイクル
エージェント設定OSGi 設定を手動で実施❌ 公開されていない(Adobe が管理)

これらのスキルを使用しないケース

代わりに UI ワークフローを使用してください。次の場合が該当します。

  • 少量のコンテンツを手動で公開する場合
  • 1 回限りの公開操作を行う場合
  • コンテンツ作成者がクイック公開または公開管理を使用できる場合

ツリーアクティベーションワークフローを使用してください。次の場合が該当します。

  • 大規模な階層構造のコンテンツツリーを公開する場合
  • カスタムロジックが不要で、数百のパスに対して一括操作を行う場合

クイックリファレンス

レプリケーション 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 以下にするか、すべてのパスを渡します — システムが自動的に分割します
イベント処理の問題
問題解決策
イベントハンドラーが呼び出されないイベントトピック定数が完全に一致していることを確認します
イベントプロパティが欠落しているイベントプロパティは必ず null チェックします
ハンドラーによって Distribution が遅くなる非同期ジョブ処理を使用し、処理をブロックしないでください

詳細ドキュメント

詳細な例、コードサンプル、高度な使用方法については、以下を参照してください。

参考資料

コメント