Skip to content

Retrying in the face of limitsยค

Grand Challenge has several limits in place to ensure fair use and system reliability.

One such limit you could run into is the maximum number of uploads. Uploads are temporarily stored before being processed in the background and automatically cleaned up afterward. If you hit the limit during a function call (e.g. add_case_to_archive) the uploads will remain unassigned. These uploads will eventually be cleaned up automatically, but can temporarily block creating any new uploads until that happens. If you retry the function call before enough uploads have been cleaned up, you might unintentionally be blocking yourself by creating yet more unassigned uploads.

The upload limit being reached is generally reported by a 400-coded response from Grand Challenge which will tell you:

"You have created too many uploads. Please try again later."

One solution could be to use a retry strategy to catch these responses, wait for a while, and continue from where your program initially ran into these limits.

Whether this strategy fits your specific use case is up to you.

The following example strategy would retry after 5 minutes: a similar construct would work for other limit-related responses.

Example

import httpx

import gcapi


class UploadRetryStrategy(gcapi.retries.SelectiveBackoffStrategy):
    """Retry strategy that handles upload limits specifically.

    In addition to the standard retryable errors handled by
    SelectiveBackoffStrategy, this strategy also retries on
    BAD_REQUEST responses that indicate the user has created too many
    uploads.
    """

    def __init__(self):
        super().__init__(
            backoff_factor=0.1,
            maximum_number_of_retries=5,  # Applies to other retriable errors
        )

    def get_delay(self, latest_response):
        delay = None  # Do not retry at all, by default

        if latest_response.status_code == httpx.codes.BAD_REQUEST:
            response_json = latest_response.json()
            non_field_errors = response_json.get("non_field_errors", [])
            if (
                len(non_field_errors) == 1
                and "you have created too many uploads"
                in non_field_errors[0].casefold()
            ):
                print("Retrying upload due to too many uploads.")
                delay = 300  # Delay for 5 minutes

        return delay

You can use it by passing it to the Client when initializing it:

token = 'my-personal-api-token'
client = gcapi.Client(
    token=token,
    retry_strategy=UploadRetryStrategy,
)