Skip to content

Commit

Permalink
Rename reducer to event handler.
Browse files Browse the repository at this point in the history
  • Loading branch information
geeknam committed Apr 16, 2017
1 parent e8f9c22 commit 1669ef8
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 30 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ from esser.entities import Entity
from esser.registry import register
from items import commands
from items import receivers
from items.reducer import ItemReducer
from items.event_handler import ItemEventHandler


@register
class Item(Entity):

reducer = ItemReducer()

# set event handler to aggregate state
event_handler = ItemEventHandler()
created = commands.CreateItem()
price_updated = commands.UpdatePrice()

Expand Down Expand Up @@ -87,14 +88,14 @@ class UpdatePrice(BaseCommand):
}
```

#### Add reducer to fold event stream
#### Add event handler to fold event stream

`items/reducer.py`
`items/event_handler.py`

```python
from esser.reducer import BaseReducer
from esser.event_handler import BaseEventHandler

class ItemReducer(BaseReducer):
class ItemEventHandler(BaseEventHandler):

def on_item_created(self, aggregate, next_event):
return self.on_created(aggregate, next_event)
Expand Down
8 changes: 5 additions & 3 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Entities / Aggregates
:members:
:undoc-members:


Repositories
==================

Expand All @@ -32,7 +33,8 @@ DynamoDB
:members:
:undoc-members:

Events

Commands
-----------------------

.. autoclass:: esser.commands.BaseCommand
Expand All @@ -48,10 +50,10 @@ Events
:undoc-members:


Reducers
Event Handlers
---------------------

.. autoclass:: esser.reducer.BaseReducer
.. autoclass:: esser.event_handler.BaseEventHandler
:members:
:undoc-members:

Expand Down
5 changes: 3 additions & 2 deletions esser/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from esser.commands import BaseCommand
from esser.repositories.dynamodb import DynamoDBRepository
from esser.utils import cached_property
from esser.signals import event_pre_save


class Entity(object):
Expand Down Expand Up @@ -46,12 +47,12 @@ def get_initial_state(self):
def get_state_at(self, version):
sequence = self.repository.get_events(version)
initial_state = self.get_last_snapshot() or self.get_initial_state()
return reduce(self.reducer.reduce, sequence, initial_state)
return reduce(self.event_handler.apply, sequence, initial_state)

def get_current_state(self):
sequence = self.repository.get_all_events()
initial_state = self.get_last_snapshot() or self.get_initial_state()
return reduce(self.reducer.reduce, sequence, initial_state)
return reduce(self.event_handler.apply, sequence, initial_state)

current_state = property(get_current_state)
cached_current_state = cached_property(get_current_state)
Expand Down
21 changes: 18 additions & 3 deletions esser/reducer.py → esser/event_handler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import re
from esser.exceptions import AggregateDeleted

re_camel_case = re.compile(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))')
re_camel_case = re.compile(
r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))'
)


def camel_case_to_spaces(value):
Expand All @@ -12,9 +14,22 @@ def camel_case_to_spaces(value):
return re_camel_case.sub(r'_\1', value).strip('_').lower()


class BaseReducer(object):
class BaseEventHandler(object):
"""
Responsible for building up the read state from all events
"""

def apply(self, aggregate, next_event):
"""Called by reduce(), this method should find the
corresponding handler based on the event name
Args:
aggregate (dict): current state of an aggregate
next_event (esser.repositories.base.Event): next event to apply
def reduce(self, aggregate, next_event):
Returns:
dict: aggregate state
"""
event_name = camel_case_to_spaces(next_event.event_type)
self.update_version(aggregate, next_event)
handler = getattr(self, 'on_%s' % event_name, None)
Expand Down
22 changes: 13 additions & 9 deletions esser/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@

class IntegrityError(Exception):
def __init__(self, errors, message='Duplicate hash and range keys'):
message = '%s: %s' % (message, errors)
super(IntegrityError, self).__init__(message)
class EsserException(Exception):

def __init__(self, errors, message=None):
message = '%s: %s' % (message or self.message, errors)
super(EsserException, self).__init__(message)
self.errors = errors


class EventValidationException(Exception):
def __init__(self, errors, message='Event validation error'):
message = '%s: %s' % (message, errors)
super(EventValidationException, self).__init__(message)
self.errors = errors
class IntegrityError(EsserException):

message = 'Duplicate hash and range keys'


class EventValidationException(EsserException):

message = 'Event validation error'


class AggregateDoesNotExist(Exception):
Expand Down
6 changes: 3 additions & 3 deletions examples/basket/aggregate.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from esser.entities import Entity
from esser.reducer import BaseReducer
from esser.event_handler import BaseEventHandler
from basket import commands
from items.aggregate import Item


class BasketReducer(BaseReducer):
class BasketEventHandler(BaseEventHandler):

def on_basket_created(self, aggregate, next_event):
return self.on_created(aggregate, next_event)
Expand All @@ -23,7 +23,7 @@ class Basket(Entity):
"""
Basket is an Aggregate root
"""
reducer = BasketReducer()
event_handler = BasketEventHandler()
created = commands.CreateBasket()
item_added = commands.AddItem()
item_added_with_validation = commands.AddItemWithExistanceValidation()
Expand Down
6 changes: 3 additions & 3 deletions examples/items/aggregate.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from esser.entities import Entity
from esser.reducer import BaseReducer
from esser.event_handler import BaseEventHandler
from esser.registry import register
from items import commands
from items import receivers


class ItemReducer(BaseReducer):
class ItemEventHandler(BaseEventHandler):

def on_item_created(self, aggregate, next_event):
return self.on_created(aggregate, next_event)
Expand All @@ -25,7 +25,7 @@ def on_colors_added(self, aggregate, next_event):
@register
class Item(Entity):

reducer = ItemReducer()
event_handler = ItemEventHandler()
price_updated = commands.UpdatePrice()
colors_added = commands.AddColors()
created = commands.CreateItem()
Expand Down

0 comments on commit 1669ef8

Please sign in to comment.