Fogmeister
Fogmeister

Reputation: 77661

Inspect Google Cloud Task Queue retry parameters from Task

I have created a Cloud Task that has a retry policy with max attempts set to (for example 4).

However, we want the Task to fallback to a default solution if the Task fails for the last time.

That is, if the Task fails on the first time we just log the error and return 500. And again for the second time. And the third. Etc... but if the current TaskRetryCount is the last attempt for that queue (i.e. 4 in this example) then we will execute some fallback behaviour before returning 500 for the last time.

I can see from the Cloud Tasks HTTP Handler docs that I can get the X-CloudTasks-TaskRetryCount from the header of the request. But it doesn't seem to have a way to get the max-attempts for the queue.

Is that something that I can get hold of?

Or am I approaching this wrongly? Is there a better way of doing what I'm trying to do.

Upvotes: 5

Views: 2539

Answers (3)

TinyTiger
TinyTiger

Reputation: 2101

If you want to execute something on the last retry you can use the below code.

It uses @google-cloud/tasks to get maxAttempts from the queue and then compares that to the taskRetryCount found in the task header.

import { CloudTasksClient } from '@google-cloud/tasks';

// Get the task queue
const tasksClient = new CloudTasksClient();
const request = {
  name: `projects/${PROJECT_ID}/locations/${LOCATION}/queues/${TASK_QUEUE_NAME}`,
};
const taskQueue = await tasksClient.getQueue(request);

// Get maxAttempts
const maxAttempts = Number(taskQueue[0].retryConfig?.maxAttempts);

// Get taskRetryCount
const taskRetryCount = Number(req.headers['x-cloudtasks-taskretrycount']);

  // We need to use "taskRetryCount + 1" to trigger something on the last retry
  // We need to check for "maxAttempts != -1" because -1 is unlimited attempts
if (maxAttempts != -1 && taskRetryCount + 1 == maxAttempts) {
  // Do something here on the last retry
}

Note 1: I had to use lowercase headers for mine to work. I.e. x-cloudtasks-taskretrycount instead of X-CloudTasks-TaskRetryCount as found in the Google Docs.

Note 2: In the answer by @Avishay28 it is suggested to use x-cloudtasks-taskexecutioncount instead of x-cloudtasks-taskretrycount, but I believe that if your trying to do something in the last retry you should be using x-cloudtasks-taskretrycount.

Here is the description taken from the docs:

  • X-CloudTasks-TaskRetryCount: The number of times this task has been retried. For the first attempt, this value is 0. This number includes attempts where the task failed due to 5XX error codes and never reached the execution phase.
  • X-CloudTasks-TaskExecutionCount: The total number of times that the task has received a response from the handler. Since Cloud Tasks deletes the task once a successful response has been received, all previous handler responses were failures. This number does not include failures due to 5XX error codes.

So if your task returns a 5xx code or something happened and the task never got executed, then taskretrycount will be higher then taskexecutioncount. And since the task will end when taskretrycount is more than maxAttempts there may be a situtation where the task will end before you can do something in the last task.

The other option is to use taskexecutioncount and never return a 5xx status error from your task, but I think that is likely to produce unexpected results in the future when you eventually forget that rule. Also it doesn't account for times when something else happened and the task never got executed.

Upvotes: 1

Avishay28
Avishay28

Reputation: 2456

You can retrieve the queue max attempts value using getQueue call and inspecting queue.retryConfig.maxAttempts, and use the header X-CloudTasks-TaskRetryCount to check the current retry, if maxAttempt != -1 && maxAttempt == (retry+1) your in the last retry.

Note that X-CloudTasks-TaskRetryCount counting only tasks that return 5xx status code, and also tasks that did not get to the execution phase (to your code). If you want to count only failed attempts happend in your exeuction phase, you should use the header X-CloudTasks-TaskExecutionCount and make sure your code return 4xx status code in case of an error. As per the docs:

X-CloudTasks-TaskExecutionCount The total number of times that the task has received a response from the handler. Since Cloud Tasks deletes the task once a successful response has been received, all previous handler responses were failures. This number does not include failures due to 5XX error codes.

Upvotes: 0

Daniel Ocando
Daniel Ocando

Reputation: 3794

Assuming that the tasks are created with Cloud Tasks the queue-level retry settings apply to all tasks in the queue that were created using Cloud Tasks (as they cannot be set on individual tasks). Calling the projects.locations.queues.get method from the REST API should return the RetryConfig settings from the Queue that include the maxAttempts field that you require.

For tasks created with the App Engine SDK you should refer to this docs (although I believe that approach is deprecated and not useful for your use case).

Upvotes: 0

Related Questions