項目ライフサイクル通知を有効にする

Important

2026 年 4 月末から、Fabricはワークロード エンドポイントへの論理的な削除と復元の通知の送信を開始します。 ワークロードマニフェストでワークロード OnDelete 有効になっている場合は、エンドポイントがこれらの新しいライフサイクル イベントを処理する準備ができていることを確認します。

項目ライフサイクル通知は、ワークロード UX がループ内にない場合でも、カスタム項目のライフサイクル イベントに関する通知を受信する機能をワークロード ビルダーに提供します。 この設定により、開始された方法に関係なく、アイテムがアイテム操作に応答できるようになります。

概要

アイテムライフサイクル通知は、ワークロードのユーザー インターフェイスの外部でアイテムが作成、更新、または削除されるシナリオに不可欠です。 このサービスは、項目ライフサイクル イベントが発生するたびにワークロードに通知し、次の操作を行うことができます。

  • 新規または削除済みアイテムのインフラストラクチャを設定または破棄する
  • 操作を許可する前にライセンスまたはクォータを検証する
  • 外部システムと状態を同期する
  • 項目操作のカスタム ビジネス ロジックを実装する
  • カスタム クリーンアップ ロジックを使用して論理的な削除シナリオを処理する

ライフサイクル通知がトリガーされるタイミング

ライフサイクル通知は、複数のソースから送信されたアイテム操作に対してトリガーされます。

パブリック API

アイテムは、Fabric のパブリック REST API を使用して作成、更新、または削除できます。ワークロードの UI を操作する必要はありません。 例えば次が挙げられます。

  • Items API を使用したオートメーションスクリプト
  • Fabricと統合するサード パーティ製アプリケーション
  • プログラムによって実行される管理操作

CI/CD パイプライン

項目は、Fabric の CI/CD 機能を使用して、自動デプロイ パイプラインの一部としてデプロイされます。 このシナリオでは:

  • Git 統合ワークフローの一部として項目が作成または更新される
  • デプロイ パイプラインは、環境間で項目を移行する。
  • デプロイ プロセス中にユーザー インターフェイスの対話は行われません

プラットフォーム制御のUXフロー

Fabricユーザー インターフェイス内であっても、プラットフォームは特定の作成および管理フローを制御します。 ワークロードは、一貫性を維持するために、次の操作の通知を受け取ります。

  • プラットフォーム ダイアログを使用した項目の作成
  • アイテムに影響するワークスペース レベルの操作
  • ワークスペース間のコピー操作または移動操作

ライフサイクル イベント

ワークロードは、次のライフサイクル イベントの通知を受け取ることができます。

作成

新しい項目が作成されたときにトリガーされます。 次のようにすることができます。

  • 必要なインフラストラクチャ (データベース、コンピューティング リソース) を設定する
  • ライセンスまたは容量クォータを検証する
  • 項目固有のリソースを初期化する
  • 検証が失敗した場合、または前提条件が満たされていない場合に操作をブロックする

アップデート

項目の定義またはプロパティが変更されたときにトリガーされます。 次のようにすることができます。

  • 関連付けられているインフラストラクチャを更新する
  • 新しい構成を検証する
  • 変更を外部システムと同期する
  • 更新プログラムがビジネス ルールに違反している場合に操作をブロックする

削除

アイテムが削除されたときにトリガーされます。 要求には、ハード削除かソフトディリートかを示す deleteType フィールドが含まれています。

  • ハード削除: 完全削除 - 関連付けられているすべてのリソースをクリーンアップする
  • 論理的な削除: アイテムは削除対象としてマークされていますが、後で復元できます。復元をサポートするために十分なメタデータとリソースを保持します

ワークロードでは、ソフト削除のさまざまな戦略を選択できます。

  • データを保持しながらコストの高いコンピューティング リソースを停止する
  • 重要なデータを低コストのストレージにアーカイブする
  • 復旧期間の完全な状態を保持する

サブジェクト トークンは、削除操作中に使用できない場合があります。 エンドポイントは、それに応じて認証を処理する必要があります。

Restore

以前にソフト削除されたアイテムが復元されるときに発生します。 エンドポイントは項目定義を受け取り、次の操作を行う必要があります。

  • 論理的な削除中に解放されたリソースを再割り当てする
  • アイテムの状態を復元し、サービスを再開する
  • 必要に応じてコンピューティング リソースまたはストレージ リソースを再初期化する

要求の形式

Fabricは、ライフサイクル イベントごとに個別のエンドポイントを呼び出します。 各要求には次のものが含まれます。

URL パス パラメーター

アイテムの識別情報は、URL パスで提供されます。

  • workspaceId - ワークスペース ID (UUID)
  • itemType - 項目の種類 (たとえば、 Contoso.FinanceAnalytics.Forecast)
  • itemId - 項目 ID (UUID)

認証ヘッダー

Authorization ヘッダーは、委任されたユーザー トークンとアプリ専用トークンの両方を含むSubjectAndAppToken1.0スキームを使用します。

SubjectAndAppToken1.0 subjectToken="<delegated token>", appToken="<S2S token>"

このデュアル トークン形式を使用すると、ワークロードで要求の配信元を検証し、ユーザー コンテキストを確認し、他のサービスを呼び出すことができます。 追加の必須ヘッダーには、 ActivityIdRequestId、および x-ms-client-tenant-idが含まれます。

これらのトークンの検証の詳細については、「 リモート エンドポイントの認証」を参照してください。

リクエストボディ

要求本文は、操作によって異なります。

  • 作成、更新、および復元: 本文には、ItemDefinition配列を持つparts オブジェクトが含まれています。 各パーツには、 pathpayload (Base64 エンコード)、および payloadTypeがあります。
  • 削除: 本文には、deleteTypeまたはHardの値を持つSoft フィールドが含まれています。

要求本文の情報を使用すると、次のことができます。

  • 作成と復元中にインフラストラクチャのセットアップの構成を抽出する
  • 更新操作の変更点を理解する
  • ブロック操作に関する情報に基づいた意思決定を行う
  • ハード削除とソフト削除に対する適切なクリーンアップの戦略を選択する

ブロッキング操作

作成操作と更新操作の場合、ワークロードはライフサイクル エンドポイントからエラー応答を返すことによって、操作をブロックできます。 これは次の場合に役立ちます。

  • ライセンスの検証: ユーザーが必要なライセンスを持っていない場合にアイテムの作成を禁止する
  • クォータの適用: ワークスペースまたは容量の制限を超えた場合に作成をブロックする
  • 構成の検証: 無効な状態を作成する更新プログラムを拒否する
  • セキュリティ ポリシー: 項目の構成に組織のポリシーを適用する

操作をブロックする場合:

  1. エンドポイントからエラー状態コード (400 や 403 など) を返す
  2. 操作がブロックされた理由を説明する明確なエラー メッセージを提供する
  3. プラットフォームによってエラー メッセージがユーザーに表示される
  4. 項目の操作が完了していません

Important

削除操作 (ハードとソフトの両方) をブロックすることはできません。 アイテムの状態に関係なく、ワークロードでクリーンアップを処理する必要があります。 復元操作は、エラー応答を返すことによってブロックできます。

ライフサイクル通知処理の実装

カスタム項目で定義されているライフサイクル通知は、Fabric内で直接処理することはできません。 代わりに、Fabricがライフサイクルのイベントを発生したときに呼び出すリモートエンドポイントを実装する必要があります。 これにより、通知処理ロジックを実行する場所と方法を完全に制御できます。

リモート エンドポイントは次のようになります。

  • An Azure Function - 簡易な通知処理のための単純なサーバーレス実行
  • An Azure Container Instance - 特定のランタイム環境を必要とする通知の場合
  • カスタム Web サービス - 複雑なオーケストレーションと処理の場合
  • 任意のコンピューティング サービス - HTTP エンドポイントを公開し、通知を処理できる限り

リモート エンドポイントの実装と構成の詳細については、「リモート エンドポイントを 有効にする」を参照してください。

コンフィギュレーション

カスタム アイテムのライフサイクル通知を有効にするには、アイテム マニフェストで通知を構成します。

アイテム マニフェストでライフサイクル通知を定義する

項目マニフェストにライフサイクル通知の構成を追加します。

<Item>
    <Name>YourItemType</Name>
    <!-- Other item configuration -->
    
    <LifecycleOperationsNotifications>
        <OnCreate>true</OnCreate>
        <OnUpdate>true</OnUpdate>
        <OnDelete>true</OnDelete>
    </LifecycleOperationsNotifications>
</Item>

処理する必要があるイベントのみを構成します。 特定のイベントの種類に対する通知が不要な場合は、値を false に設定するか、要素を省略します。

Important

OnDeleteが有効になっている場合、ワークロードはOnRestoreItem エンドポイントも実装する必要があります。 Fabricは、ソフト削除されたアイテムが復元されたときにこのエンドポイントを呼び出します。そのため、削除通知を処理するワークロードの場合は、復元通知にも対応できるように準備する必要があります。

エンドポイントの要件

ライフサイクル エンドポイントでは、次の手順を実行する必要があります。

  • HTTPS 経由でパブリックにアクセスできるようにする
  • 妥当なタイムアウト内に応答する (推奨: 30 秒)
  • 適切な HTTP 状態コードを返す
  • 指定されたトークンを使用して認証を処理する

ブロックする作成操作と更新操作の場合:

  • エラーの詳細を含む 4xx 状態コードを返す
  • 応答本文にわかりやすいエラー メッセージを含める

成功した操作、または削除操作と復元操作の場合:

  • 200 OK 状態コードを返します
  • 必要に応じて、ログ記録または追跡情報を含める

ローカル開発のサポート

ローカルの開発とテストのために、Fabric Extensibility Toolkit には、開発サーバーに組み込みのスタブ実装が用意されています。 これにより、Azureにデプロイすることなく、ローカル コンピューターで項目のライフサイクル通知をテストできます。

しくみ

ローカル開発サーバーを実行すると (Get started with Fabric Extensibility Toolkit and Register Local Web Server) は、アイテム マニフェストで定義されているすべてのライフサイクル通知がローカル コンピューターに自動的にリダイレクトされます。

開発モードでライフサイクル イベントが発生した場合:

  1. 通知はローカル開発サーバーによってインターセプトされます
  2. イベントの詳細を示すログ ステートメントがローカル コンソールに表示される
  3. サンプル実装では、項目定義と OneLake ストレージを操作する方法を示します
  4. 任意のFabric操作を呼び出すために使用できるトークンを受け取ります

このスタブ実装では、次の機能が提供されます。

  • 即時のフィードバック - ライフサイクル イベントが発生したときにコンソールでログ ステートメントを確認する
  • サンプル コード - 通知処理ロジックを構成する方法について説明します
  • OneLake 統合の例 - 通知中にアイテムの OneLake ストレージにアクセスする方法を確認する
  • トークン処理 - Fabric認証トークンを取得して使用する方法を理解する
  • 項目定義アクセス - 項目定義の完全なペイロードを表示する

開発スタブの使用

ライフサイクル通知テストにローカル開発サーバーを使用するには:

  1. クイック スタート ガイドに従ってローカル開発サーバーを起動する
  2. 登録手順を使用してローカル Web サーバーを登録する
  3. 前述のように項目マニフェストでライフサイクル通知を構成する
  4. Fabricで項目の操作 (作成、更新、削除) を実行する
  5. ローカル コンソールで通知の詳細を確認する
  6. 開発サーバー ログの OneLake の相互作用とトークン処理のサンプル コードを確認する

OneLake の相互作用の例

開発スタブには、項目の OneLake ストレージを操作する方法を示すサンプル コードが含まれています。

// Example from the development stub
const tokenExchangeService = require('./tokenExchangeService');
const oneLakeClientService = require('./oneLakeClientService');

async function handleCreateWithOneLakeAccess(req) {
  const { workspaceId, itemId } = req.params;
  const { subjectToken, tenantId } = req.authContext;

  // Exchange user token for OneLake-scoped token
  const oneLakeToken = await tokenExchangeService.getTokenForScope(
    subjectToken, tenantId, oneLakeClientService.ONELAKE_SCOPE);

  // Write to the item's OneLake storage
  const filePath = oneLakeClientService.getOneLakeFilePath(
    workspaceId, itemId, 'config.json');
  const content = JSON.stringify(req.body, null, 2);
  await oneLakeClientService.writeToOneLakeFile(oneLakeToken, filePath, content);

  console.log(`Initialized item configuration in OneLake at ${filePath}`);
}

このローカル開発エクスペリエンスを使用すると、運用エンドポイントにデプロイする前に、ライフサイクル通知ロジックを構築してテストできます。

実装例

次の例では、Fabric Extensibility Toolkit 参照実装に基づいて Node.js と Express を使用します。 各ライフサイクルイベントには、Fabricが適切な要求本文で呼び出す独自のエンドポイントがあります。 完全な API の詳細については、 項目ライフサイクル REST API リファレンスを参照してください

const express = require('express');
const { authenticateControlPlaneCall } = require('./authentication');
const router = express.Router();

// POST /workspaces/{workspaceId}/items/{itemType}/{itemId}/onCreateItem
// Request body: { definition: { parts: [{ path, payload, payloadType }] } }
router.post('/workspaces/:workspaceId/items/:itemType/:itemId/onCreateItem',
  async (req, res) => {
    const authResult = await authenticateControlPlaneCall(req, res);
    if (!authResult) return;

    const { workspaceId, itemId, itemType } = req.params;
    const { definition } = req.body;

    // Validate license before allowing creation
    const hasLicense = await checkUserLicense(req.authContext.userId);
    if (!hasLicense) {
      return res.status(403).json({
        errorCode: 'LicenseRequired',
        message: 'User does not have the required license for this item type.',
        source: 'User',
        isPermanent: true
      });
    }

    // Set up infrastructure for the new item
    await provisionResources(workspaceId, itemId, definition);

    console.log(`Created item ${itemId} of type ${itemType}`);
    res.status(200).json({});
  }
);

// POST /workspaces/{workspaceId}/items/{itemType}/{itemId}/onUpdateItem
// Request body: { definition: { parts: [{ path, payload, payloadType }] } }
router.post('/workspaces/:workspaceId/items/:itemType/:itemId/onUpdateItem',
  async (req, res) => {
    const authResult = await authenticateControlPlaneCall(req, res);
    if (!authResult) return;

    const { workspaceId, itemId } = req.params;
    const { definition } = req.body;

    // Validate the updated definition
    if (!isValidConfiguration(definition)) {
      return res.status(400).json({
        errorCode: 'InvalidConfiguration',
        message: 'Invalid configuration: required settings are missing.',
        source: 'User',
        isPermanent: true
      });
    }

    await updateResources(workspaceId, itemId, definition);

    console.log(`Updated item ${itemId}`);
    res.status(200).json({});
  }
);

// POST /workspaces/{workspaceId}/items/{itemType}/{itemId}/onDeleteItem
// Request body: { deleteType: "Hard" | "Soft" }
// Note: Subject token may not be available during delete operations.
router.post('/workspaces/:workspaceId/items/:itemType/:itemId/onDeleteItem',
  async (req, res) => {
    const authResult = await authenticateControlPlaneCall(req, res,
      { requireSubjectToken: false });
    if (!authResult) return;

    const { workspaceId, itemId } = req.params;
    const { deleteType } = req.body;

    if (deleteType === 'Hard') {
      await deleteAllResources(workspaceId, itemId);
      console.log(`Hard deleted item ${itemId}`);
    } else if (deleteType === 'Soft') {
      // Retain metadata for recovery; optionally free expensive resources
      await stopComputeResources(workspaceId, itemId);
      console.log(`Soft deleted item ${itemId}`);
    }

    res.status(200).json({});
  }
);

// POST /workspaces/{workspaceId}/items/{itemType}/{itemId}/onRestoreItem
// Request body: { definition: { parts: [{ path, payload, payloadType }] } }
// Called when a soft-deleted item is restored.
router.post('/workspaces/:workspaceId/items/:itemType/:itemId/onRestoreItem',
  async (req, res) => {
    const authResult = await authenticateControlPlaneCall(req, res,
      { requireSubjectToken: false });
    if (!authResult) return;

    const { workspaceId, itemId } = req.params;
    const { definition } = req.body;

    // Re-allocate resources freed during soft delete
    await restoreResources(workspaceId, itemId, definition);

    console.log(`Restored item ${itemId}`);
    res.status(200).json({});
  }
);

使用例

インフラストラクチャ管理

項目のライフサイクルに基づいてインフラストラクチャを自動的にプロビジョニングおよびプロビジョニング解除します。

// In onCreateItem handler: Provision resources
await createSqlDatabase(itemId);
await createStorageAccount(itemId);
await createComputeCluster(itemId);

// In onDeleteItem handler (deleteType === 'Hard'): Clean up resources
await deleteSqlDatabase(itemId);
await deleteStorageAccount(itemId);
await deleteComputeCluster(itemId);

ライセンスとクォータの検証

onCreateItem ハンドラーでライセンスと容量の要件を適用します。

// Check user license before allowing creation
const userLicense = await getUserLicense(req.authContext.userId);
if (userLicense.tier < REQUIRED_TIER_PREMIUM) {
  return res.status(403).json({
    errorCode: 'LicenseRequired',
    message: 'Premium license required for this item type.',
    source: 'User',
    isPermanent: true
  });
}

// Check workspace capacity
const workspaceUsage = await getWorkspaceUsage(workspaceId);
if (workspaceUsage.itemCount >= workspaceUsage.maxItems) {
  return res.status(403).json({
    errorCode: 'QuotaExceeded',
    message: 'Workspace item limit reached.',
    source: 'User',
    isPermanent: false
  });
}

外部システム同期

外部システムとFabric項目の同期を維持する:

// In onCreateItem handler: Sync item to external catalog
const { workspaceId, itemId, itemType } = req.params;
await externalCatalog.registerItem({
  id: itemId,
  type: itemType,
  workspaceId: workspaceId
});

// Update external monitoring
await monitoringSystem.trackItemCreated(workspaceId, itemId);

削除と復元の戦略

deleteTypeに基づいてさまざまなクリーンアップ戦略を実装し、復元を処理します。

// In onDeleteItem handler:
const { deleteType } = req.body;

if (deleteType === 'Soft') {
  // Free expensive resources but retain data for potential recovery
  await stopExpensiveCompute(itemId);
  await archiveDataToLowCostStorage(itemId);
}

if (deleteType === 'Hard') {
  // Permanent deletion - clean up everything
  await deleteAllResources(itemId);
}

// In onRestoreItem handler:
// Re-allocate resources freed during soft delete
await restartCompute(itemId);
await restoreDataFromArchive(itemId);

ベスト プラクティス

迅速に対応する

ライフサイクル エンドポイントは、可能な限り迅速に応答する必要があります。

  • 検証と迅速なセットアップ操作を同期的に実行する
  • 長時間実行するインフラストラクチャのプロビジョニングをバックグラウンド処理用にキューに入れます。
  • タイムアウトを回避するために、成功/失敗をすばやく返す

べき等性の処理

項目の操作が再試行される可能性があるため、エンドポイントは冪等性を持つ必要があります。

  • 作成する前にインフラストラクチャが既に存在するかどうかを確認する
  • 一意の識別子を使用して操作を追跡する
  • 重複する通知を適切に処理する

エラーメッセージを明確にする

操作をブロックする場合は、役に立つエラー メッセージを提供します。

// Good: Structured ErrorResponse with a clear message
return res.status(403).json({
  errorCode: 'LicenseRequired',
  message: 'Cannot create item: Premium license required. Upgrade your subscription.',
  source: 'User',
  isPermanent: true
});

// Poor: Missing structured error information
return res.status(403).json({ message: 'Forbidden' });

セキュリティ

  • すべての要求で認証トークンを検証する
  • トークンを使用して操作が正当であることを確認する
  • 検証なしでアイテム ID またはワークスペース ID を信頼しない
  • セキュリティのベスト プラクティスについては、「 リモート エンドポイントの認証 」を参照してください

監視とログ記録

  • 受信したすべてのライフサイクル通知をログに記録する
  • インフラストラクチャのプロビジョニングの成功/失敗を追跡する
  • エンドポイントのパフォーマンスとエラーを監視する
  • 監査証跡用に通知データを使用する

Troubleshooting

通知が受信されない

  • マニフェストでエンドポイント URL が正しいことを確認する
  • エンドポイントがパブリックにアクセス可能であることを確認する
  • HTTPS が正しく構成されていることを確認する
  • エンドポイント ログでエラーを確認する

操作のタイムアウト

  • エンドポイントの応答時間を最適化する
  • 実行時間の長い操作をバックグラウンド ジョブに移動する
  • 必要に応じてエンドポイントのタイムアウト設定を増やす
  • インフラストラクチャプロビジョニングのパフォーマンスを確認する

ブロックが機能しない

  • ブロックされた操作に対して 4xx 状態コードが返されていることを確認する
  • エラー メッセージが応答に含まれていることを確認する
  • タイムアウト 期間内にエンドポイントが応答することを確認する
  • 削除操作はブロックできないことに注意してください。Fabric プラットフォームは、ワークロードの応答に関係なく、アイテムを削除済みとしてマークします。