Обработка ошибок

В этом руководстве объясняется, как управлять ошибками, возникающими при выполнении шагов потока. Вы можете указать, требуется ли вмешательство пользователя для устранения ошибки или можно ли повторить попытку.

  • Возвращает ошибку, требующую действий : добавляет в журнал ошибок кнопку, которая перенаправляет пользователя на карточку конфигурации шага, позволяя ему изменить введенные данные для устранения ошибки. Чтобы отметить ошибку как требующую действий, верните AddOnsResponseService.ErrorActionability.ACTIONABLE . Чтобы отметить ошибку как не требующую действий, верните AddOnsResponseService.ErrorActionability.NOT_ACTIONABLE .
  • Повторите шаг после ошибки : поток пытается повторить шаг до 5 раз, прежде чем остановиться. Чтобы отметить ошибку как допускающую повторную попытку, верните AddOnsResponseService.ErrorRetryability.RETRYABLE . Чтобы отметить ошибку, допускающую повторную попытку, верните AddOnsResponseService.ErrorRetryability.NOT_RETRYABLE .

Вы также можете создавать собственные журналы ошибок с микросхемами, гиперссылками и стилизованным текстом, чтобы предоставить пользователям более подробный контекст ошибки.

Вернуть ошибку, требующую исправления

В следующем примере создается шаг, запрашивающий у пользователя отрицательное число. Если пользователь вводит положительное число, шаг возвращает ошибку, требующую действий, с предложением исправить введенные данные.

Следующий файл манифеста определяет входы, выходы шага и функции, вызываемые для настройки и выполнения.

JSON

{
  "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();
  }
}

Повторите шаг после ошибки.

В следующем примере создается шаг, имитирующий временный сбой. В случае возникновения ошибки шаг возвращает ошибку, которую можно повторить, что приводит к повторному выполнению шага.

Файл манифеста определяет шаг.

JSON

{
  "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();
  }
}