Prefect 2.7.4 is here with improvements to retry delays, new defaults added to .prefectignore, and more!

Hello, everyone! Prefect 2.7.4 has been released!

Highlights

Improvements to retry delays: multiple delays, exponential backoff, and jitter

When configuring task retries, you can now configure a delay for each retry! The retry_delay_seconds option accepts a list of delays for custom retry behavior. For example, the following task will wait for successively increasing intervals before the next attempt starts:

from prefect import task, flow
import random

@task(retries=3, retry_delay_seconds=[1, 10, 100])
def flaky_function():
    if random.choice([True, False]):
        raise RuntimeError("not this time!")
    return 42

Additionally, you can pass a callable that accepts the number of retries as an argument and returns a list. Prefect includes an exponential_backoff utility that will automatically generate a list of retry delays that correspond to an exponential backoff retry strategy. The following flow will wait for 10, 20, then 40 seconds before each retry.

from prefect import task, flow
from prefect.tasks import exponential_backoff
import random

@task(retries=3, retry_delay_seconds=exponential_backoff(backoff_factor=10))
def flaky_function():
    if random.choice([True, False]):
        raise RuntimeError("not this time!")
    return 42

Many users that configure exponential backoff also wish to jitter the delay times to prevent “thundering herd” scenarios, where many tasks all retry at exactly the same time, causing cascading failures. The retry_jitter_factor option can be used to add variance to the base delay. For example, a retry delay of 10 seconds with a retry_jitter_factor of 0.5 will be allowed to delay up to 15 seconds. Large values of retry_jitter_factor provide more protection against “thundering herds”, while keeping the average retry delay time constant. For example, the following task adds jitter to its exponential backoff so the retry delays will vary up to a maximum delay time of 20, 40, and 80 seconds respectively.

from prefect import task, flow
from prefect.tasks import exponential_backoff
import random

@task(
    retries=3,
    retry_delay_seconds=exponential_backoff(backoff_factor=10),
    retry_jitter_factor=1,
)
def flaky_function():
    if random.choice([True, False]):
        raise RuntimeError("not this time!")
    return 42

See the pull request for implementation details.

Other Updates

  • We increased in the default thread limit from 40 to 250 to help resolve issues when running many synchronous tasks concurrently.
  • A new prefect-google-sheets collection - big thanks to community member @Stefano Cascavilla for creating it! Feel free to head on over to the repo and give it a ️
  • prefect-gcp 0.2.0 was released with many useful additions and changes. Check it out if you use Google Cloud Platform!

As always, see the release notes for details.Thank you to everyone for your feedback and especially to @devanshdoshi9 and @quassy for their first contributions! Happy holidays!

2 Likes