رسیدگی به خطاها

این راهنما نحوه مدیریت خطاهایی را که هنگام اجرای یک مرحله از فرآیند رخ می‌دهند، توضیح می‌دهد. می‌توانید مشخص کنید که آیا یک مرحله ناموفق نیاز به اقدام کاربر برای حل شدن دارد یا می‌توان آن را دوباره امتحان کرد.

  • یک خطای قابل پیگیری را برگردانید : دکمه‌ای به گزارش خطا اضافه کنید که کاربر را به کارت پیکربندی مرحله هدایت کند و به آنها اجازه دهد ورودی‌های خود را برای حل خطا تغییر دهند. برای علامت‌گذاری یک خطا به عنوان قابل پیگیری، AddOnsResponseService.ErrorActionability.ACTIONABLE را برگردانید. برای علامت‌گذاری یک خطا به عنوان غیرقابل پیگیری، AddOnsResponseService.ErrorActionability.NOT_ACTIONABLE را برگردانید.
  • تکرار مرحله پس از بروز خطا : جریان برنامه تا ۵ بار تلاش می‌کند تا مرحله را قبل از توقف، دوباره اجرا کند. برای علامت‌گذاری یک خطا به عنوان خطایی که می‌توان دوباره آن را تکرار کرد، AddOnsResponseService.ErrorRetryability.RETRYABLE را برگردانید. برای علامت‌گذاری خطایی که نمی‌توان دوباره آن را تکرار کرد، AddOnsResponseService.ErrorRetryability.NOT_RETRYABLE را برگردانید.

همچنین می‌توانید گزارش‌های خطای سفارشی با تراشه‌ها، هایپرلینک‌ها و متن استایل‌دار ایجاد کنید تا زمینه دقیق‌تری در مورد خطا در اختیار کاربران قرار دهید.

یک خطای قابل پیگیری را برگردانید

مثال زیر مرحله‌ای را ایجاد می‌کند که از کاربر یک عدد منفی می‌خواهد. اگر کاربر عدد مثبت وارد کند، مرحله یک خطای قابل پیگیری برمی‌گرداند که کاربر را وادار به اصلاح ورودی خود می‌کند.

فایل مانیفست زیر ورودی‌ها، خروجی‌ها و توابعی که باید برای پیکربندی و اجرا فراخوانی شوند را تعریف می‌کند.

جی‌سون

{
  "timeZone": "America/Toronto",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Retry Errors Example",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "returnElementError",
          "state": "ACTIVE",
          "name": "Return Element Error Action",
          "description": "To notify the user that some error has occurred",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "The input from the user",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "outputs": [
              {
                "id": "output_1",
                "description": "The output",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfiguration",
            "onExecuteFunction": "onExecution"
          }
        }
      ]
    }
  }
}

کد زیر کارت پیکربندی را می‌سازد و منطق اجرا، از جمله مدیریت خطا، را مدیریت می‌کند.

اسکریپت برنامه‌ها

/**
 * Returns a configuration card for the step.
 * This card contains a text input field for the user.
 */
function onConfiguration() {
  let section = CardService.newCardSection()
    .addWidget(CardService.newTextInput()
      .setFieldName("value1")
      .setId("value1")
      .setTitle("Please input negative numbers!"));
  const card = CardService.newCardBuilder().addSection(section).build();
  return card;
}

/**
 * Gets an integer value from variable data, handling both string and integer formats.
 * @param {Object} variableData The variable data object from the event.
 * @return {number} The extracted integer value.
 */
function getIntValue(variableData) {
  if (variableData.stringValues) {
    return parseInt(variableData.stringValues[0]);
  }
  return variableData.integerValues[0];
}

/**
 * Executes the step.
 * If the user input is a positive number, it throws an error and returns an
 * actionable error message. Otherwise, it returns the input as an output variable.
 * @param {Object} e The event object from the workflow.
 */
function onExecution(e) {
  try {
    var input_value = getIntValue(e.workflow.actionInvocation.inputs["value1"]);
    if (input_value > 0) {
      throw new Error('Found invalid positive input value!');
    }

    // If execution is successful, return the output variable and a log.
    const styledText_1 = AddOnsResponseService.newStyledText()
      .setText("Execution completed, the number you entered was: ")
      .addStyle(AddOnsResponseService.TextStyle.ITALIC)
      .addStyle(AddOnsResponseService.TextStyle.UNDERLINE);
    const styledText_2 = AddOnsResponseService.newStyledText().setText(input_value)
      .setFontWeight(AddOnsResponseService.FontWeight.BOLD);

    const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
      .setVariables({
        "output_1": AddOnsResponseService.newVariableData().addStringValue(input_value)
      })
      .setLog(AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setStyledText(styledText_1)
        ).addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setStyledText(styledText_2)
        ));

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();

  } catch (err) {
    // If an error occurs, return an actionable error action.
    Logger.log('An error occurred: ' + err.message);

    const workflowAction = AddOnsResponseService.newReturnElementErrorAction()
      // Sets the user-facing error message.
      .setErrorLog(
        AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setText("Failed because of invalid input values!"))
      )
      // Makes the error actionable, allowing the user to correct the input.
      .setErrorActionability(AddOnsResponseService.ErrorActionability.ACTIONABLE)
      // Specifies that the error is not automatically retried.
      .setErrorRetryability(AddOnsResponseService.ErrorRetryability.NOT_RETRYABLE);

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();
  }
}

بعد از خطا، مرحله را دوباره امتحان کنید

مثال زیر مرحله‌ای را ایجاد می‌کند که یک خطای موقت را شبیه‌سازی می‌کند. اگر خطایی رخ دهد، مرحله خطایی را برمی‌گرداند که می‌توان دوباره امتحان کرد، که باعث می‌شود جریان، مرحله را دوباره اجرا کند.

فایل مانیفست، مرحله را تعریف می‌کند.

جی‌سون

{
  "timeZone": "America/Toronto",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Retry Errors Example",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "retryError",
          "state": "ACTIVE",
          "name": "Retry an error",
          "description": "Simulates a temporary failure and retries the step.",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "Any input value",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "outputs": [
              {
                "id": "output_1",
                "description": "The output",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onRetryConfiguration",
            "onExecuteFunction": "onRetryExecution"
          }
        }
      ]
    }
  }
}

کد زیر کارت پیکربندی را می‌سازد و منطق تلاش مجدد را مدیریت می‌کند.

اسکریپت برنامه‌ها

/**
 * Returns a configuration card for the step.
 * This card contains a text input field for the user.
 */
function onRetryConfiguration() {
  let section = CardService.newCardSection()
    .addWidget(CardService.newTextInput()
      .setFieldName("value1")
      .setId("value1")
      .setTitle("Enter any value"));
  const card = CardService.newCardBuilder().addSection(section).build();
  return card;
}

/**
 * Executes the step and simulates a transient error.
 * This function fails 80% of the time. When it fails, it returns an
 * error that can be retried.
 * @param {Object} e The event object from the workflow.
 */
function onRetryExecution(e) {
  try {
    // Simulate a transient error that fails 80% of the time.
    if (Math.random() < 0.8) {
      throw new Error('Simulated transient failure!');
    }

    // If execution is successful, return the output variable and a log.
    var input_value = e.workflow.actionInvocation.inputs["value1"].stringValues[0];
    const styledText = AddOnsResponseService.newStyledText()
      .setText(`Execution succeeded for input: ${input_value}`);

    const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
      .setVariables({
        "output_1": AddOnsResponseService.newVariableData().addStringValue(input_value)
      })
      .setLog(AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setStyledText(styledText)
        ));

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();

  } catch (err) {
    // If a transient error occurs, return an error message saying the step tries to run again.
    Logger.log('A error occurred, trying to run the step again: ' + err.message);

    const workflowAction = AddOnsResponseService.newReturnElementErrorAction()
      // Sets the user-facing error message.
      .setErrorLog(
        AddOnsResponseService.newWorkflowTextFormat()
        .addTextFormatElement(
          AddOnsResponseService.newTextFormatElement().setText("A temporary error occurred. The step will be retried."))
      )
      // Makes the error not actionable by the user.
      .setErrorActionability(AddOnsResponseService.ErrorActionability.NOT_ACTIONABLE)
      // Specifies that the error is automatically retried.
      .setErrorRetryability(AddOnsResponseService.ErrorRetryability.RETRYABLE);

    let hostAppAction = AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);
    return AddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();
  }
}