Skip to content

Commit

Permalink
Closes #14365: Introduce job_start and job_end signals (#14393)
Browse files Browse the repository at this point in the history
* Introduce job_start and job_end signals, and receivers to process event rules

* Complete signals documentation
  • Loading branch information
jeremystretch authored Dec 1, 2023
1 parent b812a50 commit 4fc0a99
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 20 deletions.
24 changes: 24 additions & 0 deletions docs/development/signals.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
25 changes: 5 additions & 20 deletions netbox/core/models/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

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
Expand Down Expand Up @@ -168,8 +169,8 @@ def start(self):
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):
"""
Expand All @@ -186,8 +187,8 @@ def terminate(self, status=JobStatusChoices.STATUS_COMPLETED, error=None):
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):
Expand Down Expand Up @@ -223,19 +224,3 @@ def enqueue(cls, func, instance, name='', user=None, schedule_at=None, interval=
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)
6 changes: 6 additions & 0 deletions netbox/core/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
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()
Expand Down
26 changes: 26 additions & 0 deletions netbox/extras/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
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
Expand Down Expand Up @@ -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)

0 comments on commit 4fc0a99

Please sign in to comment.