Skip to main content

Shared package for Felesh microservices with scaffold utilities

Project description

Felesh Shared Package

A foundational Python package providing scaffold utilities and SDK capabilities for all Felesh microservices. This package ensures consistent architecture patterns, code structure, and development practices across the entire microservices ecosystem.

๐ŸŽฏ Architecture Templates

Choose the architecture that fits your service requirements:

Simple Architecture

  • Best for: Traditional CRUD operations, straightforward business logic
  • Components: Models, Repositories, GenericServices, UsecaseServices, Views
  • Complexity: Low - 50% less boilerplate than CQRS
  • Use when: No event publishing, synchronous workflows, fast development needed

Event-Driven CQRS Architecture

  • Best for: Event-driven services, distributed transactions, complete audit trails
  • Components: Commands, Queries, Handlers, MessageBus, EventStore, Outbox Pattern
  • Complexity: Higher - Full CQRS with event sourcing
  • Use when: Event publishing required, zero event loss critical, distributed transactions

๐Ÿš€ Features

Shared Across All Architectures

  • Framework Support: Native integration with Django REST Framework and FastAPI
  • Unit of Work: Transaction management across repositories
  • Repository Pattern: Abstraction for data access
  • Type Safety: Full Pydantic V2 integration
  • Clean Architecture: Separation of concerns maintained

Event-Driven CQRS Only

  • CQRS Pattern: Clean separation between commands (writes) and queries (reads)
  • Event-Driven Architecture: Hybrid outbox pattern for guaranteed event delivery with zero loss
  • MessageBus: Automatic command/query routing to handlers
  • Event Store: Complete audit trail of all domain events

๐Ÿ“ฆ Installation

From Git Repository (Production)

# Install latest from develop branch (HTTPS)
uv add git+https://code.arshai.com/felesh-ai/platform/core-services/shared-package.git

# Install latest from develop branch (SSH)
uv add git+ssh://git@code.arshai.com:2222/felesh-ai/platform/core-services/shared-package.git

# Install specific version/tag
uv add git+https://code.arshai.com/felesh-ai/platform/core-services/shared-package.git@v0.1.0

# Or add to your pyproject.toml
[project.dependencies]
felesh-shared-package = { git = "https://code.arshai.com/felesh-ai/platform/core-services/shared-package.git", branch = "develop" }

From Local Path (Development)

# Install in editable mode for local development
uv add --editable /path/to/felesh_shared_package

# Or add to your pyproject.toml
[project.dependencies]
felesh-shared-package = { path = "../felesh_shared_package", editable = true }

Requirements: Python 3.13+

CLI Commands Available After Installation

Once installed, the package provides the felesh-init command:

# Check if installed correctly
felesh-init --help

# Create a new project from anywhere
felesh-init myservice --framework drf --arch simple

๐Ÿ”ง Development Setup

Code Quality Enforcement

This package uses pre-commit hooks to automatically enforce code quality standards:

# Install pre-commit hooks (one-time setup)
uv run pre-commit install
# or
make precommit-install

Once installed, hooks run automatically on every commit, checking:

  • File hygiene (trailing whitespace, EOF newlines, YAML/TOML syntax)
  • Ruff linting and formatting (auto-fixes many issues)
  • Large file detection and merge conflict markers

Manual execution (optional):

# Run hooks on all files
uv run pre-commit run --all-files
# or
make precommit-run

Makefile targets:

make lint            # Run Ruff linter
make format          # Format code with Ruff
make fix             # Auto-fix lint issues and format
make precommit-run   # Run all pre-commit hooks

๐Ÿ—๏ธ Project Structure

scaffold/
โ”œโ”€โ”€ common/                      # Shared CQRS infrastructure
โ”‚   โ”œโ”€โ”€ seedwork/               # Base classes for CQRS pattern
โ”‚   โ”‚   โ”œโ”€โ”€ commands.py         # Command DTOs and handlers
โ”‚   โ”‚   โ”œโ”€โ”€ queries.py          # Query DTOs and handlers
โ”‚   โ”‚   โ”œโ”€โ”€ events.py           # Event system and dispatching
โ”‚   โ”‚   โ”œโ”€โ”€ uow.py              # Unit of Work pattern
โ”‚   โ”‚   โ””โ”€โ”€ repositories.py     # Repository pattern
โ”‚   โ”œโ”€โ”€ adapters/               # Framework adapters
โ”‚   โ”‚   โ”œโ”€โ”€ drf/                # Django REST Framework integration
โ”‚   โ”‚   โ””โ”€โ”€ fastapi/            # FastAPI integration
โ”‚   โ””โ”€โ”€ testing/                # Test utilities and mocks
โ”œโ”€โ”€ project_templates/          # Ready-to-use project templates
โ”‚   โ”œโ”€โ”€ drf/                    # DRF project template
โ”‚   โ””โ”€โ”€ fastapi/                # FastAPI project template
โ”œโ”€โ”€ examples/                   # Example implementations
โ”‚   โ””โ”€โ”€ cqrs_patterns/          # CQRS pattern examples
โ””โ”€โ”€ init_project.py            # Project initialization script

๐Ÿšฆ Quick Start

Create a New Project

After installing the package, you can use the felesh-init CLI command from anywhere:

# Simple architecture (recommended for CRUD services)
felesh-init myservice --framework drf --arch simple

# Event-Driven CQRS architecture (for event-driven services)
felesh-init myservice --framework fastapi --arch event-driven-cqrs

# Create in specific directory
felesh-init myservice --framework drf --arch simple --path /path/to/projects

# Get help
felesh-init --help

Alternative methods (from felesh_shared_package directory):

# Using Makefile
make init-project NAME=myservice FRAMEWORK=drf ARCH=simple

# Using Python script directly
python scaffold/init_project.py myservice --framework drf --arch simple

Architecture Decision Guide

Criteria Simple Event-Driven CQRS
Event Publishing โŒ No cross-service events โœ… Publishes to Kafka
Distributed Transactions โŒ Single database โœ… Eventual consistency
Audit Trail Standard DB logs โœ… Complete event history
Team Experience โœ… Junior devs OK โš ๏ธ CQRS knowledge needed
Development Speed โœ… Faster (50% less code) โš ๏ธ More boilerplate
Use Cases CRUD, simple workflows Event-driven, complex sagas

Define Commands and Queries

from scaffold.common.seedwork import ICommand, IQuery
from pydantic import Field, EmailStr

class CreateUserCommand(ICommand):
    """Command to create a new user."""
    email: EmailStr = Field(..., description="User email")
    username: str = Field(..., min_length=3, max_length=50)
    full_name: str = Field(..., description="Full name")

class GetUserByIdQuery(IQuery):
    """Query to get user by ID."""
    user_id: int = Field(..., description="User ID")

Implement Handlers

from scaffold.common.seedwork import (
    ICommandHandler, ICommandResult, Status
)

class CreateUserHandler(ICommandHandler):
    """Handler for CreateUserCommand."""

    def __init__(self, uow, event_collector):
        self.uow = uow
        self.event_collector = event_collector

    def handle(self, command: CreateUserCommand) -> ICommandResult:
        """Execute the create user command."""
        with self.uow:
            # Business logic
            user = self.uow.user_repo.add({
                'email': command.email,
                'username': command.username,
                'full_name': command.full_name,
            })

            # Collect event (saved atomically with data)
            event = UserCreatedEvent(
                user_id=str(user['id']),
                email=user['email']
            )
            self.event_collector.add_event(event)

            self.uow.commit()

            return ICommandResult(
                status=Status.SUCCESS,
                data={'user_id': user['id']}
            )

Use with Django REST Framework

from scaffold.common.adapters.drf import CommandAPIView, QueryAPIView

class CreateUserView(CommandAPIView):
    command_class = CreateUserCommand
    handler_class = CreateUserHandler

class GetUserView(QueryAPIView):
    query_class = GetUserByIdQuery
    handler_class = GetUserByIdHandler

# urls.py
urlpatterns = [
    path('users/', CreateUserView.as_view()),
    path('users/<int:user_id>/', GetUserView.as_view()),
]

Use with FastAPI

from fastapi import FastAPI, Depends
from scaffold.common.adapters.fastapi import (
    create_command_handler_dependency
)

app = FastAPI()

@app.post("/users")
async def create_user(
    command: CreateUserCommand,
    handler = Depends(create_command_handler_dependency(CreateUserHandler))
):
    result = handler.handle(command)
    if result.is_success():
        return result.data
    raise HTTPException(status_code=400, detail=result.message)

๐Ÿ“š Documentation

All documentation is centralized in the /docs directory:

Getting Started

CQRS Pattern

Event System

Infrastructure

API Layer

Framework Adapters

Utilities

Examples

  • Examples: Working examples of all patterns

๐Ÿ”„ Migration from v1.x

Breaking Changes in v2.0:

  • Removed scaffold/drf/seedwork/ and scaffold/fastapi/seedwork/
  • All imports now from scaffold.common.seedwork and scaffold.common.adapters
  • Service pattern completely removed in favor of CQRS handlers

See Migration Guide for detailed migration instructions.

๐ŸŽฏ Best Practices

  1. Separation of Concerns: Keep commands and queries separate
  2. Single Responsibility: One handler for one command/query
  3. Explicit Transactions: Always use Unit of Work for data modifications
  4. Event-Driven: Emit events for important business operations
  5. Type Safety: Leverage Pydantic for validation
  6. Testing: Mock UoW and repositories, test business logic in isolation

๐Ÿงช Testing

def test_create_user_handler():
    # Arrange
    handler = CreateUserHandler()
    handler.uow = Mock(spec=DjangoUnitOfWork)
    handler.uow.user_repo.add.return_value = {'id': 1}

    command = CreateUserCommand(
        email="test@example.com",
        username="testuser",
        full_name="Test User"
    )

    # Act
    result = handler.handle(command)

    # Assert
    assert result.is_success()
    assert result.data['user_id'] == 1
    handler.uow.commit.assert_called_once()

๐Ÿ›๏ธ Architecture

The package implements a simplified CQRS pattern with hybrid outbox pattern for event delivery:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              API Layer (DRF/FastAPI)                         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚            Commands    โ”‚    Queries                          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚           Handlers (Business Logic)                          โ”‚
โ”‚                   โ†“                                          โ”‚
โ”‚           EventCollector (In-Memory)                         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚          Unit of Work & Repositories                         โ”‚
โ”‚                   โ†“                                          โ”‚
โ”‚      [Database] โ† ATOMIC TRANSACTION โ†’ [Outbox Events]      โ”‚
โ”‚                                              โ†“               โ”‚
โ”‚                                   [Immediate Publish 99%]    โ”‚
โ”‚                                              โ†“               โ”‚
โ”‚                                          Kafka               โ”‚
โ”‚                                                              โ”‚
โ”‚      [Background Worker] โ†’ Retry Failed Events (1%)         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Guarantees:
โœ… Zero event loss (atomic commit)
โœ… Low latency (~10-15ms for 99% of events)
โœ… Guaranteed delivery (background worker retries)

๐Ÿค Contributing

This package is used across all Felesh microservices. Any changes should be:

  1. Backward compatible when possible
  2. Thoroughly tested
  3. Documented with examples
  4. Reviewed by the architecture team

๐Ÿ“„ License

Proprietary - Felesh Project

๐Ÿ†˜ Support

  • Check examples in scaffold/examples/cqrs_patterns/
  • Review documentation in /docs directory
  • Start with INDEX.md for complete reference
  • Check TROUBLESHOOTING.md for common issues

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

felesh_framework-0.4.2.tar.gz (401.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

felesh_framework-0.4.2-py3-none-any.whl (586.2 kB view details)

Uploaded Python 3

File details

Details for the file felesh_framework-0.4.2.tar.gz.

File metadata

  • Download URL: felesh_framework-0.4.2.tar.gz
  • Upload date:
  • Size: 401.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for felesh_framework-0.4.2.tar.gz
Algorithm Hash digest
SHA256 4cd177c9441c979b590e68e8635820ab3ba5ef906976cf1422d16ed94ac80f16
MD5 88993660c7acf599f52b94dd05ba9bee
BLAKE2b-256 8f5cf5163f557f2a51c632f446cc2c7f5b3278d1e7f234929e57885a2d05ea9b

See more details on using hashes here.

File details

Details for the file felesh_framework-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: felesh_framework-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 586.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for felesh_framework-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1c26597a85405279ef90baddd84f6a1c23d54572a3ec53c3ffaeb3c1b02503ef
MD5 3a99a6b49fd6473db2ba5547a9d01170
BLAKE2b-256 a5b4dba5d2f96e56122bb42221d12cc7164ccbaa97707ecaadda84155aae8216

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page