Skip to content

Commit

Permalink
Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-raccoon-97 committed Nov 23, 2024
1 parent b2c6029 commit 8fa3b1e
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 17 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
# py-bondi
A library for creating event driven systems using domain driven design.

In process...
### Installation

```bash
pip install pybondi
```

### Introduction

This library provides a framework for modeling complex domains using an event driven architecture and the pub/sub pattern. It provides:

- An in memory message bus for handling events and commands.
- A simple in memory publisher for publishing messages to external systems.
- A base aggregate root that can collect domain events and a base aggregate class.
- A base repository class for storing and retrieving aggregates.
- A session class for managing transactions and unit of work.
- Default events for handling aggregate's state when it is added to a session, saved, or rolled back.

Soon I will be updating this README with a more detailed explanation of how to use the library.
2 changes: 1 addition & 1 deletion pybondi/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RolledBack[T: Aggregate](Event):
aggregate: T

@dataclass
class Saved[T: Aggregate](Event):
class Commited[T: Aggregate](Event):
'''
The Saved[Aggregate] event is used to signal that the aggregate has been committed in the session.
'''
Expand Down
19 changes: 15 additions & 4 deletions pybondi/messagebus.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,30 @@ def __init__(self):
self.command_handlers = dict[type[Command], Callable[[Command], None]]()
self.event_handlers = dict[type[Event], list[Callable[[Event], None]]]()

def on(self, *event_types: type[Event]):
def subscribe(self, *event_types: type[Event]):
"""
A decorator that registers a consumer for a given event type.
Parameters:
event_types: The event types to be registered.
"""
def decorator(consumer: Callable[[Event], None]):
for event_type in event_types:
self.subscribe(event_type, consumer)
self.add_event_handler(event_type, consumer)
return consumer
return decorator

def register(self, command_type: type[Command], handler: Callable[[Command], None]):
def register(self, command_type: type[Command]):
"""
A decorator that registers a handler for a given command type.
Parameters:
command_type: The type of the command.
"""
def decorator(handler: Callable[[Command], None]):
self.add_command_handler(command_type, handler)
return handler
return decorator

def add_command_handler(self, command_type: type[Command], handler: Callable[[Command], None]):
"""
Sets a handler for a given command type. A command type can only have one handler.
Parameters:
Expand All @@ -58,7 +69,7 @@ def register(self, command_type: type[Command], handler: Callable[[Command], Non
"""
self.command_handlers[command_type] = handler

def subscribe(self, event_type: type[Event], consumer: Callable[[Event], None]):
def add_event_handler(self, event_type: type[Event], consumer: Callable[[Event], None]):
"""
Adds a consumer for a given event type. An event type can have multiple consumers.
Parameters:
Expand Down
8 changes: 4 additions & 4 deletions pybondi/repository.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from pybondi.aggregate import Aggregate

class Repository(ABC):
class Repository[T: Aggregate](ABC):
"""
Repository is an abstract class that defines the interface for storing and restoring aggregates.
Expand All @@ -17,7 +17,7 @@ class Repository(ABC):
def __init__(self):
self.aggregates = dict[str, Aggregate]()

def add(self, aggregate: Aggregate):
def add(self, aggregate: T):
"""
Adds an aggregate to the internal identity map.
Expand Down Expand Up @@ -52,7 +52,7 @@ def close(self):
"""
self.aggregates.clear()

def store(self, aggregate: Aggregate):
def store(self, aggregate: T):
"""
Stores the given aggregate to the underlying storage.
Expand All @@ -62,7 +62,7 @@ def store(self, aggregate: Aggregate):
pass


def restore(self, aggregate: Aggregate):
def restore(self, aggregate: T):
"""
Restores the given aggregate from the underlying storage.
Expand Down
8 changes: 4 additions & 4 deletions pybondi/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pybondi.messagebus import Messagebus, Command, Event
from pybondi.repository import Repository
from pybondi.publisher import Publisher
from pybondi.events import Added, RolledBack, Saved
from pybondi.events import Added, RolledBack, Commited

class Session:
"""
Expand Down Expand Up @@ -50,9 +50,9 @@ def __init__(self, repository: Repository = None, publisher: Publisher = None, m

self.messagebus = messagebus or Messagebus()
for event_type, handlers in self.event_handlers.items():
[self.messagebus.subscribe(event_type, handler) for handler in handlers]
[self.messagebus.add_event_handler(event_type, handler) for handler in handlers]
for command_type, handler in self.command_handlers.items():
self.messagebus.register(command_type, handler)
self.messagebus.add_command_handler(command_type, handler)

def enqueue(self, message: Command | Event):
"""
Expand Down Expand Up @@ -116,7 +116,7 @@ def commit(self):
"""
self.run()
for aggregate in self.repository.aggregates.values():
self.dispatch(Saved(aggregate))
self.dispatch(Commited(aggregate))
self.repository.commit(), self.publisher.commit()

def rollback(self):
Expand Down
6 changes: 3 additions & 3 deletions tests/test_messagebus.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from pybondi.messagebus import Messagebus
from pybondi.events import Added, Saved
from pybondi.events import Added, Commited

messagebus = Messagebus()

@messagebus.on(Added, Saved)
@messagebus.subscribe(Added, Commited)
def handle_events(event):
pass

def test_messagebus():
assert messagebus.event_handlers[Added][0] == handle_events
assert messagebus.event_handlers[Saved][0] == handle_events
assert messagebus.event_handlers[Commited][0] == handle_events

0 comments on commit 8fa3b1e

Please sign in to comment.