演習 - 実行時間の長いタスクを管理する持続的タイマーを追加する

完了

あなたは、会社から、プロジェクト設計提案が適切なタイミングで承認されない場合にアクションを実行するエスカレーション ステップを組み込むという新しいワークフローの修正を依頼されました。

この演習では、ワークフローの実行中にタイムアウトを制御するタイマーを追加します。 また、タイムアウトを使用してワークフローの実行パスを制御する方法についても学習します。

関数アプリに moment npm パッケージを追加する

ワークフローを変更する前に、コンソールを使用して moment npm パッケージを関数アプリに追加します。

  1. サンドボックスのアクティブ化に使ったのと同じアカウントを使って、Azure portal にサインインします。

  2. Azure portal メニューまたは [ホーム] ページの [Azure サービス][すべてのリソース] を選択し、前の演習で作成した関数アプリを選択します。 [関数アプリ] ウィンドウが表示されます。

  3. 左側のメニュー バーの [開発ツール] で、[コンソール] を選択します。 関数アプリ用の [コンソール] ペインが表示されます。

  4. コンソール ウィンドウが C:\home\site\wwwroot フォルダーで開いていることを確認し、次のコマンドを実行して、このサンプル関数アプリに必要なライブラリをインストールします。

    1. 次のコマンドを実行して、TypeScript ライブラリをインストールしてください。これは、静的な型指定に必要な依存関係です。

      npm install typescript
      
    2. 次のコマンドを実行して、moment ライブラリをインストールします。これには、永続的な関数に使用できる日付/時刻の関数が含まれています。

      npm install moment
      

      これらのコマンドの完了には数秒かかる場合があります。ノード パッケージ マネージャーで警告が表示された場合は、無視してかまいません。

  5. すべてのパッケージのインストールが完了するまで待機した後、コンソール ウィンドウを閉じます。

関数アプリにエスカレーション アクティビティを追加する

  1. Azure portal のメニューまたは [ホーム] ページの [Azure サービス] で、[すべてのリソース] を選択し、関数アプリを選択します。 [関数アプリ] ウィンドウが表示されます。

  2. 画面の中央にある [関数] タブを選択してください。

  3. [関数] タブ メニュー バーで [作成] を選択してください。 [関数の作成] ペインが表示されます。

  4. [テンプレートの選択] で、[フィルター] ボックスに「Durable Functions のアクティビティ」と入力し、そのテンプレートを一覧から選択してください。 このテンプレートを使用すると、オーケストレーター関数によってアクティビティが呼び出されたときに実行される永続関数が作成されます。

  5. [テンプレートの詳細] で、[新しい関数] フィールドに関数の名前として「Escalation」を入力し、[作成] を選択します。 この関数用の [escalation] ペインが表示されます。

  6. 左側のメニュー ウィンドウの [開発者] で、[コードとテスト] を選択します。 関数の [コード + テスト] ペインが表示されます。

    index.js ファイルのコードがエディターに表示されます。

  7. 既存のコードを次のコードに置き換えます。

    module.exports = async function (context) {
        return `ESCALATION : You have not approved the project design proposal - reassigning to your Manager!  ${context.bindings.name}!`;
    };
    

    このコードでは、ワークフローがエスカレートされたことを示すメッセージが返されます。 運用システムであれば、この関数には受信者に通知するロジックやタスクを再割り当てするロジックが含まれます。

  8. 上部のメニュー バーで [保存] を選択して、新しい関数を保存します。

エスカレーション関数を使用するようにオーケストレーション関数を更新する

  1. Azure portal のメニューまたは [ホーム] ページの [Azure サービス] で、[すべてのリソース] を選択し、関数アプリを選択します。 [関数アプリ] ウィンドウが表示されます。

  2. 画面の中央にある [関数] タブを選択してください。

  3. 前の演習で作成した OrchFunction 関数を選択します。 [OrchFunction] 関数のペインが表示されます。

  4. 左側のメニュー ウィンドウの [開発者] で、[コードとテスト] を選択します。 関数の [コード + テスト] ペインが表示されます。

    index.js ファイルのコードがエディターに表示されます。

  5. 次のように moment ライブラリへの参照を追加します。

    const moment = require("moment");
    
  6. 関数の本体を次のコードに置き換えます。これにより、承認の期限が経過したかどうかがテストされます。

    module.exports = df.orchestrator(function* (context) {
        const outputs = [];
        const deadline = moment.utc(context.df.currentUtcDateTime).add(20, "s");
        const activityTask = context.df.waitForExternalEvent("Approval");
        const timeoutTask = context.df.createTimer(deadline.toDate());
    
        const winner = yield context.df.Task.any([activityTask, timeoutTask]);
        if (winner === activityTask) {
            outputs.push(yield context.df.callActivity("Approval", "Approved"));
        }
        else
        {
            outputs.push(yield context.df.callActivity("Escalation", "Head of department"));
        }
    
        if (!timeoutTask.isCompleted) {
            // All pending timers must be complete or canceled before the function exits.
            timeoutTask.cancel();
        }
    
        return outputs;
    });
    

    この演習の目的として複雑にならないように、Approval 関数が 20 秒以内に応答しない場合は、Escalation 関数が呼び出されます。 また、このコードでは、外部入力を待機するように呼び出しを Approval に変更しています。 このようにすると、テストの目的で応答が返されるタイミングを制御できます。

  7. 上部のメニュー バーで、[保存] を選択します。

Durable Functions ワークフローが開始されることを確認する

  1. Azure portal のメニューまたは [ホーム] ページの [Azure サービス] で、[すべてのリソース] を選択し、関数アプリを選択します。 [関数アプリ] ウィンドウが表示されます。

  2. [概要] ペインの上部のメニュー バーで [再起動] を選択し、再起動を求めるプロンプトが表示されたら [はい] を選択します。 再起動が完了するまで待ってから次に進みます。 [関数アプリ] ペインが表示されます。

  3. 画面の中央にある [関数] タブを選択してください。

  4. HttpStart 関数を選択します。 [HttpStart] ペインが表示されます。

  5. 上部のメニュー バーで [関数の URL の取得] を選択し、URL をコピーします。 URL は次の例のようになります。

    https://example.azurewebsites.net/api/orchestrators/{functionName}?code=AbCdEfGhIjKlMnOpQrStUvWxYz==
    

    この URL を使用して関数を実行します。

  6. 新しいブラウザー ウィンドウを開き、コピーした URL に移動します。 URL の {functionName} プレースホルダーを OrchFunction に置き換えます。次の例のようになります。

    https://example.azurewebsites.net/api/orchestrators/OrchFunction?code=AbCdEfGhIjKlMnOpQrStUvWxYz==
    

    応答メッセージには、実行を監視および管理するために使用できる、一連の URI エンドポイントが含まれます。次の例のようになります。

    {
      "id": "f0e1d2c3b4a5968778695a4b3c2d1e0f",
      "statusQueryGetUri": "https://example.azurewebsites.net/...",
      "sendEventPostUri": "https://example.azurewebsites.net/...",
      "terminatePostUri": "https://example.azurewebsites.net/...",
      "rewindPostUri": "https://example.azurewebsites.net/...",
      "purgeHistoryDeleteUri": "https://example.azurewebsites.net/..."
    }
    
  7. statusQueryGetUri の値をコピーし、Web ブラウザーを使用してその URL にアクセスしてください。 タイマーによる 20 秒間のカウントダウンを待機している間、状態が Running であることを示す応答メッセージが表示されます。これは次の例のようになります。

    {
      "name": "OrchFunction",
      "instanceId": "f0e1d2c3b4a5968778695a4b3c2d1e0f",
      "runtimeStatus": "Running",
      "input": null,
      "customStatus": null,
      "output": null,
      "createdTime": "2019-04-14T13:17:26Z",
      "lastUpdatedTime": "2019-04-14T13:17:27Z"
    }
    
  8. 20 秒間待ち、ブラウザー ウィンドウを更新します。 タイムアウトに達すると、ワークフローはエスカレート アクティビティを呼び出します。 次の例のような応答が表示されます。

    {
        "name": "OrchFunction",
        "instanceId": "f0e1d2c3b4a5968778695a4b3c2d1e0f",
        "runtimeStatus": "Completed",
        "input": null,
        "customStatus": null,
        "output": [
            "ESCALATION : You have not approved the project design proposal - reassigning to your Manager!  Head of department!"
        ],
        "createdTime": "2019-04-14T13:43:09Z",
        "lastUpdatedTime": "2019-04-14T13:43:31Z"
    }