Chuyển tới nội dung chính
Trang không công khai
Trang này không công khai. Công cụ tìm kiếm sẽ không đánh chỉ mục trang này và chỉ những ai có liên kết mới có thể truy cập trang.

New Module

thông tin

Learn how to create a new domain module in Fluvius Framework.

Creating a New Domain​

Step 1: Create Domain Folder​

Create a folder for your domain:

mkdir -p src/myapp/domains/user
cd src/myapp/domains/user

Step 2: Define State Model​

Create state.py:

from fluvius.data import DataModel, field
from datetime import datetime

class UserState(DataModel):
name: str = field()
email: str = field()
active: bool = field(initial=True)
created_at: datetime = field(default_factory=datetime.now)
updated_at: datetime = field(default_factory=datetime.now)

Step 3: Define Aggregate​

Create aggregate.py:

from fluvius.domain import Aggregate, action
from .state import UserState

class UserAggregate(Aggregate):
def __init__(self, domain):
super().__init__(domain)
self._state = None

@action(evt_key='user-created', resources=['user'])
async def create_user(self, name: str, email: str):
# Business logic
if not email or '@' not in email:
raise ValueError("Invalid email")

self._state = UserState(name=name, email=email, active=True)
return self._state

@action(evt_key='user-updated', resources=['user'])
async def update_user(self, name: str = None, email: str = None):
if self._state is None:
raise ValueError("User not created")

updates = {}
if name is not None:
updates['name'] = name
if email is not None:
if '@' not in email:
raise ValueError("Invalid email")
updates['email'] = email

updates['updated_at'] = datetime.now()
self._state = self._state.update(**updates)
return self._state

@action(evt_key='user-deactivated', resources=['user'])
async def deactivate_user(self):
if self._state is None:
raise ValueError("User not created")

self._state = self._state.update(active=False, updated_at=datetime.now())
return self._state

Step 4: Define Domain​

Create domain.py:

from fluvius.domain import Domain
from .aggregate import UserAggregate

class UserDomain(Domain):
__aggregate__ = UserAggregate

class Meta:
revision = 1
tags = ["user", "identity"]
title = "User Management Domain"
description = "Domain for managing user accounts"

Step 5: Export Domain​

Create __init__.py:

from .domain import UserDomain
from .aggregate import UserAggregate
from .state import UserState

__all__ = ['UserDomain', 'UserAggregate', 'UserState']

Using the Domain​

Register with FastAPI​

from fluvius.fastapi import FluviusFastAPI
from myapp.domains.user import UserDomain

app = FluviusFastAPI()
app.register_domain(UserDomain)

Use Domain Directly​

from fluvius.domain.context import SanicContext
from myapp.domains.user import UserDomain
from fluvius.data import UUID_GENR

# Create context
ctx = SanicContext.create(namespace='app-user')

# Create domain
domain = UserDomain(ctx)

# Set aggregate root
user_id = UUID_GENR()
domain.set_aggroot('user', user_id)

# Create command
command = domain.create_command('create-user', {
'name': 'John Doe',
'email': 'john@example.com'
})

# Process command
response = await domain.process_command(command)

Complete Example​

File Structure​

myapp/
└── domains/
└── user/
├── __init__.py
├── domain.py
├── aggregate.py
└── state.py

Complete Code​

state.py:

from fluvius.data import DataModel, field
from datetime import datetime

class UserState(DataModel):
name: str = field()
email: str = field()
active: bool = field(initial=True)
created_at: datetime = field(default_factory=datetime.now)

aggregate.py:

from fluvius.domain import Aggregate, action
from .state import UserState

class UserAggregate(Aggregate):
def __init__(self, domain):
super().__init__(domain)
self._state = None

@action(evt_key='user-created', resources=['user'])
async def create_user(self, name: str, email: str):
self._state = UserState(name=name, email=email, active=True)
return self._state

domain.py:

from fluvius.domain import Domain
from .aggregate import UserAggregate

class UserDomain(Domain):
__aggregate__ = UserAggregate

init.py:

from .domain import UserDomain
from .aggregate import UserAggregate
from .state import UserState

__all__ = ['UserDomain', 'UserAggregate', 'UserState']

Best Practices​

1. Keep Domains Focused​

Each domain should have a single responsibility:

# Good: Focused domain
class UserDomain(Domain):
# User management only
pass

# Bad: Too many responsibilities
class UserOrderPaymentDomain(Domain):
# Too many concerns
pass

2. Use Meaningful Names​

Use clear, descriptive names:

# Good: Clear names
@action(evt_key='user-account-activated')

# Bad: Unclear names
@action(evt_key='user-updated')

3. Validate in Aggregates​

Enforce business rules in aggregates:

@action(evt_key='user-created')
async def create_user(self, name: str, email: str):
# Validate business rules
if not email or '@' not in email:
raise ValueError("Invalid email")
pass

4. Use Type Hints​

Always use type hints:

@action(evt_key='user-created')
async def create_user(self, name: str, email: str) -> dict:
return {'name': name, 'email': email}

Next Steps​