Skip to content

Commit

Permalink
Merge pull request #72 from marier-nico/fix/multiple-invocation-bug
Browse files Browse the repository at this point in the history
fix: stop leaking processors with multiple invoke
  • Loading branch information
marier-nico committed May 27, 2022
2 parents 4064b46 + d613907 commit 3c04bbe
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/content/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
- v3.1.3: Fix a bug with invocation when an event matches several filters.
- v3.1.2: Fix an incorrect import.
- v3.1.1: Relax pydantic requirements to help dependency management for downstream projects.
- v3.1.0: Add error handling strategies for processors.
- v3.0.1: Improve the import path for results.
- v3.0.0:
Expand Down
5 changes: 4 additions & 1 deletion src/event_processor/event_processor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Contains the EventProcessor class."""
import inspect
from copy import copy
from types import ModuleType
from typing import Dict, Callable, Tuple, List, Union

Expand Down Expand Up @@ -103,7 +104,9 @@ def invoke(self, event: Dict) -> Union[Result, List[Result]]:
for (filter_, rank), processors in self.processors.items():
if filter_.matches(event):
if rank > highest_rank:
matching, highest_rank = processors, rank
# We take a copy here to avoid mutating the list of processors associated with a filter if we also
# end up hitting the elif just below.
matching, highest_rank = copy(processors), rank
elif rank == highest_rank:
matching.extend(processors)

Expand Down
23 changes: 23 additions & 0 deletions src/tests/test_event_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,29 @@ def a_test():
assert called is True


def test_invoke_calls_processors_once_per_invoke_with_multiple_matched_processors_and_all_matches_invocation_strategy():
event_processor = EventProcessor(invocation_strategy=InvocationStrategies.ALL_MATCHES)
filter_a = Exists("a")
filter_b = Exists("b")
a_calls = 0
b_calls = 0

@event_processor.processor(filter_a)
def a_test():
nonlocal a_calls
a_calls += 1

@event_processor.processor(filter_b)
def b_test():
nonlocal b_calls
b_calls += 1

event_processor.invoke({"a": 0, "b": 0})
event_processor.invoke({"a": 0, "b": 0})
assert a_calls == 2
assert b_calls == 2


def test_invoke_raises_for_no_matching_processors(event_processor):

with pytest.raises(InvocationError):
Expand Down

0 comments on commit 3c04bbe

Please sign in to comment.