Skip to content

Instantly share code, notes, and snippets.

View mariobittencourt's full-sized avatar

Mario Bittencourt mariobittencourt

  • SSENSE
  • Montreal
View GitHub Profile
@mariobittencourt
mariobittencourt / payment_created.py
Created May 27, 2020 20:54
Domain event + payment created event
from datetime import datetime
from abc import ABC, ABCMeta, abstractmethod
class DomainEvent(ABC, metaclass=ABCMeta):
@abstractmethod
def __init__(self, aggregate_id: str, occurred_at: str):
self.type = self.__class__.__name__
self.aggregate_id = aggregate_id
self.occurred_at = occurred_at
@mariobittencourt
mariobittencourt / payment.py
Last active May 27, 2020 21:18
Payment entity + create + record_that
from __future__ import annotations
from typing import List
from src.domain.models.domain_event import DomainEvent
from src.domain.models.payment_created import PaymentCreated
class Payment:
def __init__(self, payment_id: str):
self._payment_id = payment_id
self._events = []
@mariobittencourt
mariobittencourt / payment.py
Last active May 27, 2020 22:40
validation of business invariants for payment creation
from __future__ import annotations
from typing import List
from src.domain.models.domain_event import DomainEvent
from src.domain.models.payment_created import PaymentCreated
class Payment:
def __init__(self, payment_id: str):
self._payment_id = payment_id
self._events = []
class Payment:
# ... existing methods
def refund(self, amount_refunded: float, refund_id: str) -> None:
# business rules
if self.status != 'SETTLED':
raise Exception('Only settled payments can be refunded')
if amount_refunded > self.amount_due:
raise Exception('You can only refund amounts equal or smaller than the amount due')
@mariobittencourt
mariobittencourt / payment_refunded.py
Created May 27, 2020 22:45
Payment Refunded event
class PaymentRefunded(DomainEvent):
def __init__(self, aggregate_id: str, amount_refunded: float, refund_id: str, occurred_at: str = datetime.utcnow().isoformat()):
super().__init__(aggregate_id, occurred_at)
self.amount_refunded = amount_refunded
self.refund_id = refund_id
@mariobittencourt
mariobittencourt / payment.py
Created May 27, 2020 22:56
Dynamic binding
def method_dispatch(func):
dispatcher = functools.singledispatch(func)
def wrapper(*args, **kw):
return dispatcher.dispatch(args[1].__class__)(*args, **kw)
wrapper.register = dispatcher.register
functools.update_wrapper(wrapper, func)
return wrapper
@mariobittencourt
mariobittencourt / event_store_payment_repository.py
Last active May 27, 2020 23:29
Payment Repository - Event Store
class EventStorePaymentRepository(PaymentRepository):
def __init__(self, username: str, password: str):
self._loop = asyncio.get_event_loop()
# photonpump is a client that interfaces with event store
self._client = photonpump.connect(loop=self._loop, username=username, password=password)
self._connected = False
async def save(self, payment: Payment) -> bool:
await self._check_connection()
@mariobittencourt
mariobittencourt / event_store_payment_repository.py
Created May 27, 2020 23:19
Event Store Payment Repository : find by id
class EventStorePaymentRepository(PaymentRepository):
# ... existing code
async def find_by_id(self, payment_id: str) -> Optional[Payment]:
await self._check_connection()
stream_name = self._create_stream_name(payment_id)
payment = Payment(payment_id)
async for event in self._client.iter(stream=stream_name, from_event=0):
await self._reconstruct_from_event(event, payment)
@mariobittencourt
mariobittencourt / order.json
Last active December 14, 2020 11:58
Order
{
"customer": {
"S": "Mr Buy More"
},
"deliveryAddress": {
"S": "My place.com"
},
"events": {
"L": [
{
@mariobittencourt
mariobittencourt / dynamo.json
Created June 9, 2020 19:33
DynamoDB records to lambda
{
"Records": [
{
"eventID": "54436bc389eb70304e166170e60a3644",
"eventName": "INSERT",
"eventVersion": "1.1",
"eventSource": "aws:dynamodb",
"awsRegion": "your-region",
"dynamodb": {