From c047bf4441b65513b1afaf6bc51546750d6f61d4 Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Thu, 25 Jul 2024 16:38:42 +0200 Subject: [PATCH] Switch BackgroundJob to regular methods Instead of using a class method for run(), a regular method is used for this purpose. This gives the possibility to add more convenience methods in the future, e.g. for interacting with the job object or for logging, as implemented for scripts. --- docs/plugins/development/background-tasks.md | 8 +++----- netbox/core/jobs.py | 5 ++--- netbox/extras/jobs.py | 13 +++++-------- netbox/utilities/jobs.py | 12 +++++++++--- netbox/utilities/tests/test_jobs.py | 8 +++----- 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/docs/plugins/development/background-tasks.md b/docs/plugins/development/background-tasks.md index b5afd48af..08a3a9825 100644 --- a/docs/plugins/development/background-tasks.md +++ b/docs/plugins/development/background-tasks.md @@ -19,9 +19,8 @@ class MyTestJob(BackgroundJob): class Meta: name = "My Test Job" - @classmethod - def run(cls, job, *args, **kwargs): - obj = job.object + def run(self, *args, **kwargs): + obj = self.job.object # your logic goes here ``` @@ -62,8 +61,7 @@ class MyHousekeepingJob(BackgroundJob): class Meta: name = "Housekeeping" - @classmethod - def run(cls, job, *args, **kwargs): + def run(self, *args, **kwargs): # your logic goes here ``` ```python title="__init__.py" diff --git a/netbox/core/jobs.py b/netbox/core/jobs.py index e7e70dad7..1e4cd7ad6 100644 --- a/netbox/core/jobs.py +++ b/netbox/core/jobs.py @@ -17,9 +17,8 @@ class SyncDataSourceJob(BackgroundJob): class Meta: name = 'Synchronization' - @classmethod - def run(cls, job, *args, **kwargs): - datasource = DataSource.objects.get(pk=job.object_id) + def run(self, *args, **kwargs): + datasource = DataSource.objects.get(pk=self.job.object_id) try: datasource.sync() diff --git a/netbox/extras/jobs.py b/netbox/extras/jobs.py index eb7eb1681..5d9f921ce 100644 --- a/netbox/extras/jobs.py +++ b/netbox/extras/jobs.py @@ -26,14 +26,12 @@ class ScriptJob(BackgroundJob): # where jobs other than this one are used. Therefore, it is hidden, resulting in a cleaner job table overview. name = '' - @staticmethod - def run_script(script, job, request, data, commit): + def run_script(self, script, request, data, commit): """ Core script execution task. We capture this within a method to allow for conditionally wrapping it with the event_tracking context manager (which is bypassed if commit == False). Args: - job: The Job associated with this execution request: The WSGI request associated with this execution (if any) data: A dictionary of data to be passed to the script upon execution commit: Passed through to Script.run() @@ -80,10 +78,9 @@ class ScriptJob(BackgroundJob): # Update the job data regardless of the execution status of the job. Successes should be reported as well as # failures. finally: - job.data = script.get_job_data() + self.job.data = script.get_job_data() - @classmethod - def run(cls, job, data, request=None, commit=True, **kwargs): + def run(self, data, request=None, commit=True, **kwargs): """ Run the script. @@ -93,7 +90,7 @@ class ScriptJob(BackgroundJob): request: The WSGI request associated with this execution (if any) commit: Passed through to Script.run() """ - script = ScriptModel.objects.get(pk=job.object_id).python_class() + script = ScriptModel.objects.get(pk=self.job.object_id).python_class() # Add files to form data if request: @@ -107,4 +104,4 @@ class ScriptJob(BackgroundJob): # Execute the script. If commit is True, wrap it with the event_tracking context manager to ensure we process # change logging, event rules, etc. with event_tracking(request) if commit else nullcontext(): - cls.run_script(script, job, request, data, commit) + self.run_script(script, request, data, commit) diff --git a/netbox/utilities/jobs.py b/netbox/utilities/jobs.py index 251eb395c..28dd61c8e 100644 --- a/netbox/utilities/jobs.py +++ b/netbox/utilities/jobs.py @@ -27,13 +27,19 @@ class BackgroundJob(ABC): class Meta: pass + def __init__(self, job): + """ + Args: + job: The specific `Job` this `BackgroundJob` helper class is executing. + """ + self.job = job + @classproperty def name(cls): return getattr(cls.Meta, 'name', cls.__name__) - @classmethod @abstractmethod - def run(cls, *args, **kwargs): + def run(self, *args, **kwargs): """ Run the job. @@ -51,7 +57,7 @@ class BackgroundJob(ABC): """ try: job.start() - cls.run(job, *args, **kwargs) + cls(job).run(*args, **kwargs) job.terminate() except Exception as e: diff --git a/netbox/utilities/tests/test_jobs.py b/netbox/utilities/tests/test_jobs.py index cb0acd76a..462f53814 100644 --- a/netbox/utilities/tests/test_jobs.py +++ b/netbox/utilities/tests/test_jobs.py @@ -10,8 +10,7 @@ from core.choices import JobStatusChoices class TestBackgroundJob(BackgroundJob): - @classmethod - def run(cls, *args, **kwargs): + def run(self, *args, **kwargs): pass @@ -54,9 +53,8 @@ class BackgroundJobTest(BackgroundJobTestCase): class ErroredBackgroundJob(TestBackgroundJob): EXP = Exception('Test error') - @classmethod - def run(cls, *args, **kwargs): - raise cls.EXP + def run(self, *args, **kwargs): + raise self.EXP job = ErroredBackgroundJob.enqueue(immediate=True)