mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-01 13:06:45 +00:00
Let plugins decide if events should be processed or not (#5618)
* add wants_process_event to EventMixin in register_event this function get called and the task is just offload if the plugin returns true * add tests for wants_process_event * fix comments for register_event after code changes * add documentation for EventMixin.wants_process_event * avoid pre-formatting log messages --------- Co-authored-by: Oliver Lippert <oliver@lipperts-web.de>
This commit is contained in:
parent
7fa0c6d280
commit
46b0d77418
@ -65,11 +65,16 @@ def register_event(event, *args, **kwargs):
|
|||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
|
||||||
for slug, plugin in registry.plugins.items():
|
for slug, plugin in registry.plugins.items():
|
||||||
|
if not plugin.mixin_enabled('events'):
|
||||||
|
continue
|
||||||
|
|
||||||
if plugin.mixin_enabled('events'):
|
|
||||||
|
|
||||||
if plugin.is_active():
|
|
||||||
# Only allow event registering for 'active' plugins
|
# Only allow event registering for 'active' plugins
|
||||||
|
if not plugin.is_active():
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Let the plugin decide if it wants to process this event
|
||||||
|
if not plugin.wants_process_event(event):
|
||||||
|
continue
|
||||||
|
|
||||||
logger.debug("Registering callback for plugin '%s'", slug)
|
logger.debug("Registering callback for plugin '%s'", slug)
|
||||||
|
|
||||||
|
@ -9,6 +9,15 @@ class EventMixin:
|
|||||||
Implementing classes must provide a "process_event" function:
|
Implementing classes must provide a "process_event" function:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def wants_process_event(self, event):
|
||||||
|
"""Function to subscribe to events.
|
||||||
|
|
||||||
|
Return true if you're interested in the given event, false if not.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Default implementation always returns true (backwards compatibility)
|
||||||
|
return True
|
||||||
|
|
||||||
def process_event(self, event, *args, **kwargs):
|
def process_event(self, event, *args, **kwargs):
|
||||||
"""Function to handle events.
|
"""Function to handle events.
|
||||||
|
|
||||||
|
32
InvenTree/plugin/samples/event/filtered_event_sample.py
Normal file
32
InvenTree/plugin/samples/event/filtered_event_sample.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""Sample plugin which responds to events."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from plugin import InvenTreePlugin
|
||||||
|
from plugin.mixins import EventMixin
|
||||||
|
|
||||||
|
logger = logging.getLogger('inventree')
|
||||||
|
|
||||||
|
|
||||||
|
class FilteredEventPluginSample(EventMixin, InvenTreePlugin):
|
||||||
|
"""A sample plugin which provides supports for triggered events."""
|
||||||
|
|
||||||
|
NAME = "FilteredEventPlugin"
|
||||||
|
SLUG = "filteredsampleevent"
|
||||||
|
TITLE = "Triggered by test.event only"
|
||||||
|
|
||||||
|
def wants_process_event(self, event):
|
||||||
|
"""Return whether given event should be processed or not."""
|
||||||
|
return event == "test.event"
|
||||||
|
|
||||||
|
def process_event(self, event, *args, **kwargs):
|
||||||
|
"""Custom event processing."""
|
||||||
|
print(f"Processing triggered event: '{event}'")
|
||||||
|
print("args:", str(args))
|
||||||
|
print("kwargs:", str(kwargs))
|
||||||
|
|
||||||
|
# Issue warning that we can test for
|
||||||
|
if settings.PLUGIN_TESTING:
|
||||||
|
logger.debug('Event `%s` triggered in sample plugin', event)
|
52
InvenTree/plugin/samples/event/test_filtered_event_sample.py
Normal file
52
InvenTree/plugin/samples/event/test_filtered_event_sample.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
"""Unit tests for event_sample sample plugins."""
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from common.models import InvenTreeSetting
|
||||||
|
from plugin import registry
|
||||||
|
from plugin.base.event.events import trigger_event
|
||||||
|
|
||||||
|
from .filtered_event_sample import logger
|
||||||
|
|
||||||
|
|
||||||
|
class FilteredEventPluginSampleTests(TestCase):
|
||||||
|
"""Tests for EventPluginSample."""
|
||||||
|
|
||||||
|
def test_run_event(self):
|
||||||
|
"""Check if the event is issued."""
|
||||||
|
# Activate plugin
|
||||||
|
config = registry.get_plugin('filteredsampleevent').plugin_config()
|
||||||
|
config.active = True
|
||||||
|
config.save()
|
||||||
|
|
||||||
|
InvenTreeSetting.set_setting('ENABLE_PLUGINS_EVENTS', True, change_user=None)
|
||||||
|
|
||||||
|
# Enable event testing
|
||||||
|
settings.PLUGIN_TESTING_EVENTS = True
|
||||||
|
# Check that an event is issued
|
||||||
|
with self.assertLogs(logger=logger, level="DEBUG") as cm:
|
||||||
|
trigger_event('test.event')
|
||||||
|
self.assertIn('DEBUG:inventree:Event `test.event` triggered in sample plugin', cm[1])
|
||||||
|
|
||||||
|
# Disable again
|
||||||
|
settings.PLUGIN_TESTING_EVENTS = False
|
||||||
|
|
||||||
|
def test_ignore_event(self):
|
||||||
|
"""Check if the event is issued."""
|
||||||
|
# Activate plugin
|
||||||
|
config = registry.get_plugin('filteredsampleevent').plugin_config()
|
||||||
|
config.active = True
|
||||||
|
config.save()
|
||||||
|
|
||||||
|
InvenTreeSetting.set_setting('ENABLE_PLUGINS_EVENTS', True, change_user=None)
|
||||||
|
|
||||||
|
# Enable event testing
|
||||||
|
settings.PLUGIN_TESTING_EVENTS = True
|
||||||
|
# Check that an event is issued
|
||||||
|
with self.assertLogs(logger=logger, level="DEBUG") as cm:
|
||||||
|
trigger_event('test.some.other.event')
|
||||||
|
self.assertNotIn('DEBUG:inventree:Event `test.some.other.event` triggered in sample plugin', cm[1])
|
||||||
|
|
||||||
|
# Disable again
|
||||||
|
settings.PLUGIN_TESTING_EVENTS = False
|
@ -15,9 +15,9 @@ When a certain (server-side) event occurs, the background worker passes the even
|
|||||||
{% include 'img.html' %}
|
{% include 'img.html' %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
### Example
|
### Example (all events)
|
||||||
|
|
||||||
Implementing classes must provide a `process_event` function:
|
Implementing classes must at least provide a `process_event` function:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
class EventPlugin(EventMixin, InvenTreePlugin):
|
class EventPlugin(EventMixin, InvenTreePlugin):
|
||||||
@ -36,6 +36,34 @@ class EventPlugin(EventMixin, InvenTreePlugin):
|
|||||||
print(f"Processing triggered event: '{event}'")
|
print(f"Processing triggered event: '{event}'")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Example (specific events)
|
||||||
|
|
||||||
|
If you want to process just some specific events, you can also implement the `wants_process_event` function to decide if you want to process this event or not. This function will be executed synchronously, so be aware that it should contain simple logic.
|
||||||
|
|
||||||
|
Overall this function can reduce the workload on the background workers significantly since less events are queued to be processed.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class EventPlugin(EventMixin, InvenTreePlugin):
|
||||||
|
"""
|
||||||
|
A simple example plugin which responds to 'salesordershipment.completed' event on the InvenTree server.
|
||||||
|
|
||||||
|
This example simply prints out the event information.
|
||||||
|
A more complex plugin can run enhanced logic on this event.
|
||||||
|
"""
|
||||||
|
|
||||||
|
NAME = "EventPlugin"
|
||||||
|
SLUG = "event"
|
||||||
|
TITLE = "Triggered Events"
|
||||||
|
|
||||||
|
def wants_process_event(self, event):
|
||||||
|
"""Here you can decide if this event should be send to `process_event` or not."""
|
||||||
|
return event == "salesordershipment.completed"
|
||||||
|
|
||||||
|
def process_event(self, event, *args, **kwargs):
|
||||||
|
"""Here you can run you'r specific logic."""
|
||||||
|
print(f"Sales order was completely shipped: '{args}' '{kwargs}'")
|
||||||
|
```
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
Events are passed through using a string identifier, e.g. `build.completed`
|
Events are passed through using a string identifier, e.g. `build.completed`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user