Skip to content

Conversation

crgwbr
Copy link
Contributor

@crgwbr crgwbr commented Jul 15, 2025

In the RQ backend, if the _django_tasks_exceptions metadata key is missing or empty, but the job has failed in the past, the Job.task_result would throw this exception:

IndexError: pop from empty list
  File "rq/job.py", line 1507, in execute_failure_callback
    self.failure_callback(self, self.connection, *exc_info)
  File "django_tasks/backends/rq.py", line 154, in failed_callback
    task_result = job.task_result
  File "django/utils/functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "django_tasks/backends/rq.py", line 127, in task_result
    exception_class_path=exception_classes.pop(),

Then, since Job.task_result is accessed in Job.perform, this exception would prevent any further jobs from being queued. This commit handles the case of an empty or missing _django_tasks_exceptions metadata key by substituting in builtins.Exception for the missing exception class path.

In the RQ backend, if the `_django_tasks_exceptions` metadata key is missing or
empty, but the job has failed in the past, the `Job.task_result` would throw
this exception:

```
IndexError: pop from empty list
  File "rq/job.py", line 1507, in execute_failure_callback
    self.failure_callback(self, self.connection, *exc_info)
  File "django_tasks/backends/rq.py", line 154, in failed_callback
    task_result = job.task_result
  File "django/utils/functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "django_tasks/backends/rq.py", line 127, in task_result
    exception_class_path=exception_classes.pop(),
```

Then, since `Job.task_result` is accessed in `Job.perform`, this exception would
prevent any further jobs from being queued. This commit handles the case of an
empty or missing _django_tasks_exceptions metadata key by substituting in
`builtins.Exception` for the missing exception class path.
# Get the underlying RQ job
job = cast(RQBackend, default_task_backend)._get_job(result.id)
self.assertIsNotNone(job)
assert job is not None
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: What's the reason for this assertion? Or is it just to make mypy happy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you got it—it's to make mypy happy.

Copy link
Owner

@RealOrangeOne RealOrangeOne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for submitting this! Other than a question, this patch looks great!

@RealOrangeOne RealOrangeOne merged commit 75a01d8 into RealOrangeOne:master Jul 17, 2025
57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants