#Wondering what happens if functions fail in V3 tasks.

1 messages · Page 1 of 1 (latest)

static salmon
#

Hi all,

I was reading an article on the Trigger.dev website about writing durable tasks and have a question about a specific section. This is the one I'm talking about: https://trigger.dev/blog/v3-announcement#writing-regular-async-code-with-no-timeouts-and-durability

It shows a code snippet that uses a rollback function to revert a certain action if any errors happen after the rollback function is used. I can't seem to find this function anywhere. I happen to have a use case for it, because I am calling an API of a third party service in my task, but if any errors happen after that API call, I have to revert the changes (or do I?).

I remember that in V2, you could use the io.runTask function to "pick up where you left off" if anything goes wrong, so that certain functions are only executed once, even if the job fails. I am wondering how this works in V3. I somewhat understand the article mentioned above, but I am still a bit struggling to understand how this works exactly in V3. Should I implement this rollback function (as mentioned in the article)? If so, where do I find this rollback function? If not, will the task automatically skip the functions that were successfully executed and start at the failing functions?

Hopefully someone can help me understand this!

Write regular code and get durability with no timeouts. This means writing long-running tasks is far easier than before.

kindred saddle
static salmon
woven cedar
static salmon
# woven cedar Do you mean "must-retry"? Because we don't do anything with reverting

I mean that certain API calls inside my tasks should not be re-executed if the tasks fails and is retried. For example, if, inside a task, I make an API call to transfer funds to a user and the next function after that API call fails, I do want the whole task to be retried, but that API call specifically should not be retried. It shouldn't transfer the funds on every retry, only on the first one. Not all of the AP calls are like this, but some shouldn't be executed after the first call in cases like the example above.

In V2, this was possible by wrapping these important API calls or functions inside a io.runTask, so that these won't be executed again if the job fails and is retried. I'm wondering how I accomplish this in V3 tasks.

#

The example in the article has a different approach though. It uses a rollback function, which I can't seem to find in the SDK

woven cedar
#

But yea the way to accomplish what you want is to wrap the API call to transfer funds in a subtask, trigger that using triggerAndWait , and passing an idempotency key

#

That way if something fails further down, and the parent task is retried, the transfer funds task will not be retried

#

The other option is to use our idempotency key stuff and do your own caching

static salmon
#

Understood!, Thank you!

woven cedar
# static salmon Understood!, Thank you!

Actually, we're considering slightly changing the idempotency key semantics and I wonder if I could pick your brain on how you think it should work. Basically right now, if you are in a task.run function, and you triggerAndWait a child task passing in an idempotency key, we will cache that result no matter if the child task succeeds or fails. So if further down in the parent task there is an error, and you retry the parent task, when the child task is triggered again, the cached success or failure result will be returned.

#

The change I want to make is to change it so the child task will be rerun if it failed the first time

static salmon
static salmon
# woven cedar The change I want to make is to change it so the child task will be rerun if it ...

I agree that the child task should be rerun if it failed, because I feel like a child task should be treated like any other task. It's something that can be triggered and might fail. If it does fail, it should be rerun for the maximum amount of attempts (can be manually set per task as per documentation). It is the developer's responsibility (mine in this case) to make sure to set a maximum amount of attempts if it's an expensive operation. The result of a task should only be cached if it succeeds and has an idempotency key.

woven cedar
#

(Also thanks for getting back with your thoughts 🫡)

static salmon
#

I'm not sure if that's the current behaviour, but what do you think?

woven cedar
static salmon
woven cedar
#

So when re-attempting the parent run, you want to get back the cached failed result of the child task?

static salmon
#

Because in my opinion, there is a solid reason for that child task to fail multiple attempts.

woven cedar
#

But we return a result type from triggerAndWait, which allows you to handle the result (success or fail) of the child task

static salmon
#

So in this case, I can manually throw the AbortTaskRunError

woven cedar
#

Yea maybe we just need to document this better

static salmon
woven cedar