Skip to content

Commit 579d1e9

Browse files
authored
Check for a valid Task before rendering its link (#318)
1 parent 64e26ab commit 579d1e9

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

scheduler/templates/admin/scheduler/job_detail.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
{% block content_title %}
1616
<h2>Job {{ job.name }}
17-
{% if job.is_scheduled_task %}
17+
{% if job.is_scheduled_task and job|scheduled_task %}
1818
<small>
1919
<a href="{{ job|scheduled_task }}">Link to scheduled job</a>
2020
</small>

scheduler/templatetags/scheduler_tags.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ def get_item(dictionary: Dict, key):
3030

3131

3232
@register.filter
33-
def scheduled_task(job: JobModel) -> Task:
34-
django_scheduled_task = get_scheduled_task(*job.args)
35-
return django_scheduled_task.get_absolute_url()
33+
def scheduled_task(job: JobModel) -> Optional[Task]:
34+
try:
35+
django_scheduled_task = get_scheduled_task(*job.args)
36+
return django_scheduled_task.get_absolute_url()
37+
except ValueError:
38+
return None
3639

3740

3841
@register.filter

scheduler/tests/test_views/test_queue_registry_jobs.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from scheduler.helpers.queues import get_queue
77
from scheduler.tests.jobs import test_job
88
from scheduler.tests.test_views.base import BaseTestCase
9+
from scheduler.tests.testtools import task_factory
10+
from scheduler.models import TaskType, Task
911

1012

1113
class QueueRegistryJobsViewTest(BaseTestCase):
@@ -90,3 +92,51 @@ def test_started_jobs(self):
9092
registry.add(queue.connection, job.name, time.time() + 20)
9193
res = self.client.get(reverse("queue_registry_jobs", args=[queue_name, "active"]))
9294
self.assertEqual(res.context["jobs"], [job])
95+
96+
def test_missing_task_doesnt_crash_job_detail_page(self):
97+
"""
98+
Ensure that when a Task gets deleted and its Job doesn't get cleaned, the
99+
job detail page doesn't raise an exception.
100+
"""
101+
queue_name = "django_tasks_scheduler_test"
102+
103+
# No jobs in the queue
104+
res = self.client.get(reverse("queue_registry_jobs", args=[queue_name, "scheduled"]))
105+
self.assertEqual(res.status_code, 200)
106+
self.assertEqual(res.context["jobs"], [])
107+
108+
task = task_factory(TaskType.ONCE, queue="django_tasks_scheduler_test")
109+
110+
res = self.client.get(reverse("queue_registry_jobs", args=[queue_name, "scheduled"]))
111+
self.assertEqual(res.status_code, 200)
112+
job = res.context["jobs"][0]
113+
self.assertTrue(job)
114+
self.assertTrue(job.is_scheduled_task)
115+
self.assertEqual(job.scheduled_task_id, task.pk)
116+
117+
# Job detail page works
118+
url = reverse("job_details", args=[job.name])
119+
res = self.client.get(url)
120+
self.assertEqual(200, res.status_code)
121+
self.assertIn("job", res.context)
122+
self.assertEqual(res.context["job"], job)
123+
self.assertNotContains(res, "ValueError(&#x27;Invalid task type OnceTaskType&#x27;)")
124+
self.assertContains(res, "Link to scheduled job")
125+
126+
# Delete all tasks in bulk, this doesn't trigger the signal
127+
# that would delete the corresponding scheduled jobs.
128+
Task.objects.all().delete()
129+
130+
# The job lingers around :(
131+
res = self.client.get(reverse("queue_registry_jobs", args=[queue_name, "scheduled"]))
132+
self.assertEqual(res.status_code, 200)
133+
self.assertTrue(job in res.context["jobs"])
134+
135+
# Job detail doesn't raise a 500
136+
url = reverse("job_details", args=[job.name])
137+
res = self.client.get(url)
138+
self.assertEqual(200, res.status_code)
139+
self.assertIn("job", res.context)
140+
self.assertEqual(res.context["job"], job)
141+
self.assertContains(res, "ValueError(&#x27;Invalid task type OnceTaskType&#x27;)")
142+
self.assertNotContains(res, "Link to scheduled job")

0 commit comments

Comments
 (0)