연습 - 지속성 타이머를 추가하여 장기 실행 작업을 관리합니다.

완료됨

회사에서 프로젝트 디자인 제안서가 제때 승인되지 않으면 조치를 취하는 에스컬레이션 단계를 통합하도록 새 워크플로를 수정하라는 요청을 받았습니다.

이 연습에서는 워크플로를 실행하는 동안 시간 제한을 제어하는 타이머를 추가할 것입니다. 또한 시간 제한을 사용하여 워크플로가 수행하는 실행 경로를 제어하는 방법을 알아봅니다.

함수 앱에 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 activity를 입력하고 목록에서 해당 템플릿을 선택합니다. 이 템플릿은 오케스트레이터 함수에 의해 작업이 호출될 때 실행되는 지속성 함수를 만듭니다.

  5. 템플릿 세부 정보에서 새 함수 필드에 함수 이름으로 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 함수가 호출됩니다. 또한 코드는 외부 입력을 기다리도록 승인에 대한 호출을 변경합니다. 이렇게 하면 테스트 목적으로 응답이 돌아올 때 제어할 수 있습니다.

  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 값을 복사하고 웹 브라우저를 사용하여 해당 URL로 이동합니다. 타이머가 20초를 카운트다운하기를 기다리는 동안 상태가 실행 중임을 보여 주는 응답 메시지가 표시됩니다. 이 메시지는 다음 예와 유사합니다.

    {
      "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"
    }