Skip to content

Latest commit

 

History

History
206 lines (165 loc) · 5.97 KB

File metadata and controls

206 lines (165 loc) · 5.97 KB

Project Structure

ecommerce-order-api/
│
├── src/                          # Source code
│   ├── core/                     # Cloud-agnostic business logic
│   │   └── order_service.py      # OrderService class (main business logic)
│   │
│   └── handlers/                 # Cloud provider-specific handlers
│       ├── aws_lambda_handler.py    # AWS Lambda handler
│       ├── azure_function_handler.py # Azure Functions handler
│       └── gcp_function_handler.py  # GCP Cloud Functions handler
│
├── tests/                        # Unit tests
│   └── test_order_service.py     # Tests for core service
│
├── database/                     # Database scripts
│   └── schema.sql                # PostgreSQL schema
│
├── aws/                          # AWS-specific deployment files
│   └── template.yaml             # SAM template
│
├── scripts/                      # Deployment and utility scripts
│   └── deploy_aws.sh             # AWS deployment script
│
├── requirements.txt              # Python dependencies
├── .env.example                  # Environment variables template
├── test_order.json              # Sample order data for testing
└── README.md                    # Documentation

Architecture Overview

Core Layer (Cloud-Agnostic)

The src/core/ directory contains business logic that works identically across all cloud providers:

  • order_service.py: Contains the OrderService class with all order management logic
    • create_order(): Creates new orders with validation
    • get_order(): Retrieves orders with tenant isolation
    • list_orders(): Lists orders with pagination
    • Database operations
    • Data validation

Handler Layer (Cloud-Specific)

The src/handlers/ directory contains thin wrapper handlers for each cloud provider:

  • aws_lambda_handler.py: AWS Lambda-specific code

    • Extracts Cognito claims from API Gateway event
    • Formats responses for API Gateway
    • Routes HTTP methods to core service
  • azure_function_handler.py: Azure Functions-specific code

    • Extracts Azure AD claims
    • Uses Flask-style request/response
    • Routes to core service
  • gcp_function_handler.py: GCP Cloud Functions-specific code

    • Extracts Firebase/Identity Platform claims
    • Uses functions-framework
    • Routes to core service

Benefits of This Architecture

  1. Easy Migration: Change only the handler, core logic stays the same
  2. Testing: Test business logic independently of cloud provider
  3. Consistency: Same behavior across all cloud providers
  4. Maintenance: Update business logic once, works everywhere
  5. Multi-cloud: Deploy to multiple clouds simultaneously

Data Flow

Request
  ↓
API Gateway / Azure Functions / GCP HTTP
  ↓
Cloud-Specific Handler
  - Extract auth claims
  - Parse request
  ↓
OrderService (Core Logic)
  - Validate data
  - Execute business rules
  - Database operations
  ↓
PostgreSQL Database
  ↓
Response
  - Format for cloud provider
  - Return to client

Key Design Patterns

Dependency Injection

The OrderService receives database configuration, making it testable and flexible:

db_config = get_db_config()  # Handler-specific
order_service = OrderService(db_config)  # Cloud-agnostic

Tenant Isolation

Every operation includes tenant_id for multi-tenant security:

order = order_service.create_order(
    tenant_id='tenant-123',  # From auth claims
    user_id='user-456',
    order_data=data
)

Error Handling

Consistent error handling across all handlers:

  • Validation errors → 400 Bad Request
  • Not found → 404
  • Server errors → 500

Testing Strategy

  1. Unit Tests: Test OrderService with mocked database
  2. Integration Tests: Test handlers with test database
  3. E2E Tests: Test deployed API with real requests

Database Design

Multi-Tenancy

  • All queries filtered by tenant_id
  • Compound indexes: (tenant_id, created_by), (tenant_id, order_id)
  • Row-level security (optional, can be added)

Audit Trail

  • created_by: User who created the order
  • created_by_email: Email for audit purposes
  • created_at, updated_at: Timestamp tracking

Data Integrity

  • Foreign keys with CASCADE delete
  • CHECK constraints on status and quantities
  • NOT NULL constraints on required fields

Security Considerations

  1. Authentication: Handled by cloud provider's gateway
  2. Authorization: Tenant isolation in all queries
  3. SQL Injection: Parameterized queries via psycopg2
  4. Secrets: Never hardcode, use provider secret managers
  5. HTTPS: Enforced by API Gateway/Functions

Performance Optimization

  1. Indexes: Strategic indexes on frequently queried columns
  2. Connection Management: Reuse connections when possible
  3. Pagination: Limit results to prevent large payloads
  4. Caching: Add Redis/ElastiCache for read-heavy workloads

Extending the API

To add new endpoints:

  1. Add method to OrderService (core logic)
  2. Add route handler in each cloud handler
  3. Update tests
  4. Update API documentation

Example - Add update order:

# In order_service.py
def update_order(self, order_id, tenant_id, updates):
    # Core logic here
    pass

# In aws_lambda_handler.py
def handle_update_order(path_parameters, body, order_service, auth_claims):
    order = order_service.update_order(
        order_id=path_parameters['order_id'],
        tenant_id=auth_claims['tenant_id'],
        updates=body
    )
    return create_response(200, {'order': order})

Monitoring and Logging

Each cloud provider has built-in monitoring:

  • AWS: CloudWatch Logs and Metrics
  • Azure: Application Insights
  • GCP: Cloud Logging and Monitoring

Add structured logging:

import logging
logger = logging.getLogger(__name__)

logger.info('Order created', extra={
    'order_id': order_id,
    'tenant_id': tenant_id,
    'amount': total_amount
})