Relax requirement for Jobs to reference a specific object

This commit is contained in:
Jeremy Stretch 2024-07-24 15:58:32 -04:00
parent 62380fb605
commit d6432fbcb8
3 changed files with 37 additions and 26 deletions

View File

@ -0,0 +1,24 @@
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('core', '0011_move_objectchange'),
]
operations = [
migrations.AlterField(
model_name='job',
name='object_type',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name='jobs',
to='contenttypes.contenttype'
),
),
]

View File

@ -31,6 +31,8 @@ class Job(models.Model):
to='contenttypes.ContentType', to='contenttypes.ContentType',
related_name='jobs', related_name='jobs',
on_delete=models.CASCADE, on_delete=models.CASCADE,
blank=True,
null=True
) )
object_id = models.PositiveBigIntegerField( object_id = models.PositiveBigIntegerField(
blank=True, blank=True,
@ -197,13 +199,13 @@ class Job(models.Model):
job_end.send(self) job_end.send(self)
@classmethod @classmethod
def enqueue(cls, func, instance, name='', user=None, schedule_at=None, interval=None, run_now=False, **kwargs): def enqueue(cls, func, instance=None, name='', user=None, schedule_at=None, interval=None, run_now=False, **kwargs):
""" """
Create a Job instance and enqueue a job using the given callable Create a Job instance and enqueue a job using the given callable
Args: Args:
func: The callable object to be enqueued for execution func: The callable object to be enqueued for execution
instance: The NetBox object to which this job pertains instance: The NetBox object to which this job pertains (optional)
name: Name for the job (optional) name: Name for the job (optional)
user: The user responsible for running the job user: The user responsible for running the job
schedule_at: Schedule the job to be executed at the passed date and time schedule_at: Schedule the job to be executed at the passed date and time
@ -211,13 +213,17 @@ class Job(models.Model):
run_now: Run the job immediately without scheduling it in the background. Should be used for interactive run_now: Run the job immediately without scheduling it in the background. Should be used for interactive
management commands only. management commands only.
""" """
object_type = ObjectType.objects.get_for_model(instance, for_concrete_model=False) if instance:
object_type = ObjectType.objects.get_for_model(instance, for_concrete_model=False)
object_id = instance.pk
else:
object_type = object_id = None
rq_queue_name = get_queue_for_model(object_type.model) rq_queue_name = get_queue_for_model(object_type.model)
queue = django_rq.get_queue(rq_queue_name) queue = django_rq.get_queue(rq_queue_name)
status = JobStatusChoices.STATUS_SCHEDULED if schedule_at else JobStatusChoices.STATUS_PENDING status = JobStatusChoices.STATUS_SCHEDULED if schedule_at else JobStatusChoices.STATUS_PENDING
job = Job.objects.create( job = Job.objects.create(
object_type=object_type, object_type=object_type,
object_id=instance.pk, object_id=object_id,
name=name, name=name,
status=status, status=status,
scheduled=schedule_at, scheduled=schedule_at,

View File

@ -161,30 +161,11 @@ class SystemJob(ScheduledJob):
for system background tasks. for system background tasks.
The main use case for this method is to schedule jobs programmatically instead of using user events, e.g. to start The main use case for this method is to schedule jobs programmatically instead of using user events, e.g. to start
jobs when the plugin is loaded in NetBox. For this purpose, the `setup()` method can be used to setup a new schedule jobs when the plugin is loaded in NetBox. For this purpose, the `setup()` method can be used to set up a new
outside of the request-response cycle. It will register the new schedule right after all plugins are loaded and the schedule outside the request-response cycle. It will register the new schedule right after all plugins are loaded
database is connected. Then `schedule()` will take care of scheduling a single job at a time. and the database is connected. Then `schedule()` will take care of scheduling a single job at a time.
""" """
@classmethod
def enqueue(cls, *args, **kwargs):
kwargs.pop('instance', None)
return super().enqueue(instance=Job(), *args, **kwargs)
@classmethod
def schedule(cls, *args, **kwargs):
kwargs.pop('instance', None)
return super().schedule(instance=Job(), *args, **kwargs)
@classmethod
def handle(cls, job, *args, **kwargs):
# A job requires a related object to be handled, or internal methods will fail. To avoid adding an extra model
# for this, the existing job object is used as a reference. This is not ideal, but it works for this purpose.
job.object = job
job.object_id = None # Hide changes from UI
super().handle(job, *args, **kwargs)
@classmethod @classmethod
def setup(cls, *args, **kwargs): def setup(cls, *args, **kwargs):
""" """