1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #14365: Introduce job_start and job_end signals (#14393)

* Introduce job_start and job_end signals, and receivers to process event rules

* Complete signals documentation
This commit is contained in:
Jeremy Stretch
2023-11-30 19:36:41 -05:00
committed by GitHub
parent b812a50ca2
commit 4fc0a999ea
4 changed files with 61 additions and 20 deletions

View File

@ -9,3 +9,27 @@ This signal is sent by models which inherit from `CustomValidationMixin` at the
### Receivers
* `extras.signals.run_custom_validators()`
## core.job_start
This signal is sent whenever a [background job](../features/background-jobs.md) is started.
### Receivers
* `extras.signals.process_job_start_event_rules()`
## core.job_end
This signal is sent whenever a [background job](../features/background-jobs.md) is terminated.
### Receivers
* `extras.signals.process_job_end_event_rules()`
## core.pre_sync
This signal is sent when the [DataSource](../models/core/datasource.md) model's `sync()` method is called.
## core.post_sync
This signal is sent when a [DataSource](../models/core/datasource.md) finishes synchronizing.

View File

@ -12,6 +12,7 @@ from django.utils.translation import gettext as _
from core.choices import JobStatusChoices
from core.models import ContentType
from core.signals import job_end, job_start
from extras.constants import EVENT_JOB_END, EVENT_JOB_START
from netbox.config import get_config
from netbox.constants import RQ_QUEUE_DEFAULT
@ -168,8 +169,8 @@ class Job(models.Model):
self.status = JobStatusChoices.STATUS_RUNNING
self.save()
# Handle events
self.process_event(event=EVENT_JOB_START)
# Send signal
job_start.send(self)
def terminate(self, status=JobStatusChoices.STATUS_COMPLETED, error=None):
"""
@ -186,8 +187,8 @@ class Job(models.Model):
self.completed = timezone.now()
self.save()
# Handle events
self.process_event(event=EVENT_JOB_END)
# Send signal
job_end.send(self)
@classmethod
def enqueue(cls, func, instance, name='', user=None, schedule_at=None, interval=None, **kwargs):
@ -223,19 +224,3 @@ class Job(models.Model):
queue.enqueue(func, job_id=str(job.job_id), job=job, **kwargs)
return job
def process_event(self, event):
"""
Process any EventRules relevant to the passed job event (i.e. start or stop).
"""
from extras.models import EventRule
from extras.events import process_event_rules
# Fetch any event rules matching this object type and action
event_rules = EventRule.objects.filter(
**{f'type_{event}': True},
content_types=self.object_type,
enabled=True
)
process_event_rules(event_rules, self.object_type.model, event, self.data, self.user.username)

View File

@ -4,10 +4,16 @@ from django.dispatch import Signal, receiver
from .models import ConfigRevision
__all__ = (
'job_end',
'job_start',
'post_sync',
'pre_sync',
)
# Job signals
job_start = Signal()
job_end = Signal()
# DataSource signals
pre_sync = Signal()
post_sync = Signal()

View File

@ -8,6 +8,10 @@ from django.dispatch import receiver, Signal
from django.utils.translation import gettext_lazy as _
from django_prometheus.models import model_deletes, model_inserts, model_updates
from core.signals import job_end, job_start
from extras.constants import EVENT_JOB_END, EVENT_JOB_START
from extras.events import process_event_rules
from extras.models import EventRule
from extras.validators import CustomValidator
from netbox.config import get_config
from netbox.context import current_request, events_queue
@ -235,3 +239,25 @@ def validate_assigned_tags(sender, instance, action, model, pk_set, **kwargs):
for tag in model.objects.filter(pk__in=pk_set, object_types__isnull=False).prefetch_related('object_types'):
if ct not in tag.object_types.all():
raise AbortRequest(f"Tag {tag} cannot be assigned to {ct.model} objects.")
#
# Event rules
#
@receiver(job_start)
def process_job_start_event_rules(sender, **kwargs):
"""
Process event rules for jobs starting.
"""
event_rules = EventRule.objects.filter(type_job_start=True, enabled=True, content_types=sender.object_type)
process_event_rules(event_rules, sender.object_type.model, EVENT_JOB_START, sender.data, sender.user.username)
@receiver(job_end)
def process_job_end_event_rules(sender, **kwargs):
"""
Process event rules for jobs terminating.
"""
event_rules = EventRule.objects.filter(type_job_end=True, enabled=True, content_types=sender.object_type)
process_event_rules(event_rules, sender.object_type.model, EVENT_JOB_END, sender.data, sender.user.username)