Skip to content

Commit 4fc0a99

Browse files
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
1 parent b812a50 commit 4fc0a99

File tree

4 files changed

+61
-20
lines changed

4 files changed

+61
-20
lines changed

docs/development/signals.md

+24
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,27 @@ This signal is sent by models which inherit from `CustomValidationMixin` at the
99
### Receivers
1010

1111
* `extras.signals.run_custom_validators()`
12+
13+
## core.job_start
14+
15+
This signal is sent whenever a [background job](../features/background-jobs.md) is started.
16+
17+
### Receivers
18+
19+
* `extras.signals.process_job_start_event_rules()`
20+
21+
## core.job_end
22+
23+
This signal is sent whenever a [background job](../features/background-jobs.md) is terminated.
24+
25+
### Receivers
26+
27+
* `extras.signals.process_job_end_event_rules()`
28+
29+
## core.pre_sync
30+
31+
This signal is sent when the [DataSource](../models/core/datasource.md) model's `sync()` method is called.
32+
33+
## core.post_sync
34+
35+
This signal is sent when a [DataSource](../models/core/datasource.md) finishes synchronizing.

netbox/core/models/jobs.py

+5-20
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from core.choices import JobStatusChoices
1414
from core.models import ContentType
15+
from core.signals import job_end, job_start
1516
from extras.constants import EVENT_JOB_END, EVENT_JOB_START
1617
from netbox.config import get_config
1718
from netbox.constants import RQ_QUEUE_DEFAULT
@@ -168,8 +169,8 @@ def start(self):
168169
self.status = JobStatusChoices.STATUS_RUNNING
169170
self.save()
170171

171-
# Handle events
172-
self.process_event(event=EVENT_JOB_START)
172+
# Send signal
173+
job_start.send(self)
173174

174175
def terminate(self, status=JobStatusChoices.STATUS_COMPLETED, error=None):
175176
"""
@@ -186,8 +187,8 @@ def terminate(self, status=JobStatusChoices.STATUS_COMPLETED, error=None):
186187
self.completed = timezone.now()
187188
self.save()
188189

189-
# Handle events
190-
self.process_event(event=EVENT_JOB_END)
190+
# Send signal
191+
job_end.send(self)
191192

192193
@classmethod
193194
def enqueue(cls, func, instance, name='', user=None, schedule_at=None, interval=None, **kwargs):
@@ -223,19 +224,3 @@ def enqueue(cls, func, instance, name='', user=None, schedule_at=None, interval=
223224
queue.enqueue(func, job_id=str(job.job_id), job=job, **kwargs)
224225

225226
return job
226-
227-
def process_event(self, event):
228-
"""
229-
Process any EventRules relevant to the passed job event (i.e. start or stop).
230-
"""
231-
from extras.models import EventRule
232-
from extras.events import process_event_rules
233-
234-
# Fetch any event rules matching this object type and action
235-
event_rules = EventRule.objects.filter(
236-
**{f'type_{event}': True},
237-
content_types=self.object_type,
238-
enabled=True
239-
)
240-
241-
process_event_rules(event_rules, self.object_type.model, event, self.data, self.user.username)

netbox/core/signals.py

+6
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44
from .models import ConfigRevision
55

66
__all__ = (
7+
'job_end',
8+
'job_start',
79
'post_sync',
810
'pre_sync',
911
)
1012

13+
# Job signals
14+
job_start = Signal()
15+
job_end = Signal()
16+
1117
# DataSource signals
1218
pre_sync = Signal()
1319
post_sync = Signal()

netbox/extras/signals.py

+26
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
from django.utils.translation import gettext_lazy as _
99
from django_prometheus.models import model_deletes, model_inserts, model_updates
1010

11+
from core.signals import job_end, job_start
12+
from extras.constants import EVENT_JOB_END, EVENT_JOB_START
13+
from extras.events import process_event_rules
14+
from extras.models import EventRule
1115
from extras.validators import CustomValidator
1216
from netbox.config import get_config
1317
from netbox.context import current_request, events_queue
@@ -235,3 +239,25 @@ def validate_assigned_tags(sender, instance, action, model, pk_set, **kwargs):
235239
for tag in model.objects.filter(pk__in=pk_set, object_types__isnull=False).prefetch_related('object_types'):
236240
if ct not in tag.object_types.all():
237241
raise AbortRequest(f"Tag {tag} cannot be assigned to {ct.model} objects.")
242+
243+
244+
#
245+
# Event rules
246+
#
247+
248+
@receiver(job_start)
249+
def process_job_start_event_rules(sender, **kwargs):
250+
"""
251+
Process event rules for jobs starting.
252+
"""
253+
event_rules = EventRule.objects.filter(type_job_start=True, enabled=True, content_types=sender.object_type)
254+
process_event_rules(event_rules, sender.object_type.model, EVENT_JOB_START, sender.data, sender.user.username)
255+
256+
257+
@receiver(job_end)
258+
def process_job_end_event_rules(sender, **kwargs):
259+
"""
260+
Process event rules for jobs terminating.
261+
"""
262+
event_rules = EventRule.objects.filter(type_job_end=True, enabled=True, content_types=sender.object_type)
263+
process_event_rules(event_rules, sender.object_type.model, EVENT_JOB_END, sender.data, sender.user.username)

0 commit comments

Comments
 (0)