|
|
@@ -113,6 +113,17 @@ def enqueue_event(queue, instance, request, event_type):
|
|
|
def process_event_rules(event_rules, object_type, event):
|
|
|
"""
|
|
|
Process a list of EventRules against an event.
|
|
|
+
|
|
|
+ Notes on event sources:
|
|
|
+ - Object change events (created/updated/deleted) are enqueued via
|
|
|
+ enqueue_event() during an HTTP request.
|
|
|
+ These events include a request object and legacy request
|
|
|
+ attributes (e.g. username, request_id) for backward compatibility.
|
|
|
+ - Job lifecycle events (JOB_STARTED/JOB_COMPLETED) are emitted by
|
|
|
+ job_start/job_end signal handlers and may not include a request
|
|
|
+ context.
|
|
|
+ Consumers must not assume that fields like `username` are always
|
|
|
+ present.
|
|
|
"""
|
|
|
|
|
|
for event_rule in event_rules:
|
|
|
@@ -132,16 +143,22 @@ def process_event_rules(event_rules, object_type, event):
|
|
|
queue_name = get_config().QUEUE_MAPPINGS.get('webhook', RQ_QUEUE_DEFAULT)
|
|
|
rq_queue = get_queue(queue_name)
|
|
|
|
|
|
+ # For job lifecycle events, `username` may be absent because
|
|
|
+ # there is no request context.
|
|
|
+ # Prefer the associated user object when present, falling
|
|
|
+ # back to the legacy username attribute.
|
|
|
+ username = getattr(event.get('user'), 'username', None) or event.get('username')
|
|
|
+
|
|
|
# Compile the task parameters
|
|
|
params = {
|
|
|
- "event_rule": event_rule,
|
|
|
- "object_type": object_type,
|
|
|
- "event_type": event['event_type'],
|
|
|
- "data": event_data,
|
|
|
- "snapshots": event.get('snapshots'),
|
|
|
- "timestamp": timezone.now().isoformat(),
|
|
|
- "username": event['username'],
|
|
|
- "retry": get_rq_retry()
|
|
|
+ 'event_rule': event_rule,
|
|
|
+ 'object_type': object_type,
|
|
|
+ 'event_type': event['event_type'],
|
|
|
+ 'data': event_data,
|
|
|
+ 'snapshots': event.get('snapshots'),
|
|
|
+ 'timestamp': timezone.now().isoformat(),
|
|
|
+ 'username': username,
|
|
|
+ 'retry': get_rq_retry(),
|
|
|
}
|
|
|
if 'request' in event:
|
|
|
# Exclude FILES - webhooks don't need uploaded files,
|
|
|
@@ -158,11 +175,12 @@ def process_event_rules(event_rules, object_type, event):
|
|
|
|
|
|
# Enqueue a Job to record the script's execution
|
|
|
from extras.jobs import ScriptJob
|
|
|
+
|
|
|
params = {
|
|
|
- "instance": event_rule.action_object,
|
|
|
- "name": script.name,
|
|
|
- "user": event['user'],
|
|
|
- "data": event_data
|
|
|
+ 'instance': event_rule.action_object,
|
|
|
+ 'name': script.name,
|
|
|
+ 'user': event['user'],
|
|
|
+ 'data': event_data,
|
|
|
}
|
|
|
if 'snapshots' in event:
|
|
|
params['snapshots'] = event['snapshots']
|
|
|
@@ -179,7 +197,7 @@ def process_event_rules(event_rules, object_type, event):
|
|
|
object_type=object_type,
|
|
|
object_id=event_data['id'],
|
|
|
object_repr=event_data.get('display'),
|
|
|
- event_type=event['event_type']
|
|
|
+ event_type=event['event_type'],
|
|
|
)
|
|
|
|
|
|
else:
|