I have a usecase where a method which adds a row to a table needs to be retried in case of any exception. I am using @retry decorator of retrying to achieve this.
One of the cases is when there is a change of password of the db. I am using the arg retry_on_exception to catch whatever exception. The issue I am facing is, I want the password fetch to happen in the method I am passing to retry_on_exception.
My code so far,
@retry(stop_max_attempt_number=3, retry_on_exception=retry_if_db_error_or_passwd_change)
def add_request_to_db(self, req_id):
with make_session(self.session_maker) as session:
session.merge(RequestHolder(request_id=req_id))
session.commit()
and retry_if_db_error_or_passwd_change is like
def retry_if_db_error_or_passwd_change(exception, class_reference):
is_db_exception = isinstance(exception, DBRetryExceededException)
is_operational_error = isinstance(exception, OperationalError)
if is_db_exception:
return True
elif is_operational_error or 'Access denied ' in exception:
fetch_password(class_reference)
return True
My question is how do I send the class reference also with retry_if_db_error_or_passwd_change when passing the callable to retry_on_exception ?
Solution 1
Instead of using the raised exception as the basis of the retry via
retry_on_exception
, you can change it to be based on the return viaretry_on_result
. Here, we can pass theself
argument.retry_on_result
would then receive the object and can act accordingly.retry_on_result
would still receive the response but should just ignore and wouldn't retry.retry_if_db_error_or_passwd_change
was able to receive both the exception and the reference toself
since it correctly printed the current value ofself.value
(increasing number) and was able to stop whenRuntimeError
occurred.Solution 2
This is inspired by the answer from @blhsing. Wrap the class method during class initialization so that you can inject the class reference
self
.