A comprehensive FastAPI application that implements partner request workflow and real-time chat functionality for DealNest. Users can send partner requests to connect with other users, engage in real-time chat with presence tracking, and receive read receipts.
- User Management: Create and manage users with email and name
- Partner Requests: Send, receive, and respond to partner requests
- Partnership Creation: Automatic partnership creation when requests are accepted
- Email Notifications: Mock email notifications for request events
- Chat Channels: Create channels with multiple users
- Real-Time Messaging: WebSocket-based instant messaging
- Presence Tracking: See who's online/offline with last seen timestamps
- Read Receipts: Know when messages have been read
- WebSocket Events: Real-time presence changes and message notifications
- SQLite Database: Simple SQLite database for data persistence
- Redis Support: Optional Redis for presence storage (falls back to in-memory)
- Comprehensive Testing: 24 tests covering all functionality
- Auto Documentation: Interactive API docs at
/docs
- Python 3.9+
- Poetry (for dependency management)
-
Clone the repository (if not already done):
git clone https://github.com/emekastack/assessment-api cd assessment-api -
Install dependencies using Poetry:
poetry install
-
Set up environment variables:
cp .env.example .env # Edit .env file with your specific configuration if needed -
Activate the virtual environment:
poetry shell
-
Start the development server:
poetry run python -m app.main
Or alternatively:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8004
-
Access the API:
- API Base URL:
http://localhost:8004 - Interactive API Documentation:
http://localhost:8004/docs - Alternative API Documentation:
http://localhost:8004/redoc
- API Base URL:
POST /users/- Create a new userGET /users/- Get all usersGET /users/{user_id}- Get a specific user by ID
POST /partner-requests/- Create a new partner requestGET /partner-requests/received/{user_id}/- Get pending requests received by a userPOST /partner-requests/respond/- Respond to a partner request (accept/reject)
POST /chat/channels/- Create a new chat channelGET /chat/channels/{channel_id}- Get channel detailsPOST /chat/channels/{channel_id}/messages/- Send a message to a channelGET /chat/channels/{channel_id}/messages/- Get messages from a channelPOST /chat/messages/{message_id}/mark-read/- Mark a message as readGET /chat/presence/{user_id}- Get user presence statusGET /chat/presence/online/- Get list of online usersWebSocket /chat/ws/{user_id}- Real-time WebSocket connection
# Create Alice
curl -X POST "http://localhost:8004/users/" \
-H "Content-Type: application/json" \
-d '{"email": "alice@example.com", "name": "Alice"}'
# Create Bob
curl -X POST "http://localhost:8004/users/" \
-H "Content-Type: application/json" \
-d '{"email": "bob@example.com", "name": "Bob"}'curl -X POST "http://localhost:8004/partner-requests/" \
-H "Content-Type: application/json" \
-d '{"sender_id": 1, "recipient_id": 2}'curl -X GET "http://localhost:8004/partner-requests/received/2/"# Accept the request
curl -X POST "http://localhost:8004/partner-requests/respond/" \
-H "Content-Type: application/json" \
-d '{"request_id": 1, "action": "accept"}'
# Or reject the request
curl -X POST "http://localhost:8004/partner-requests/respond/" \
-H "Content-Type: application/json" \
-d '{"request_id": 1, "action": "reject"}'# Create a chat channel
curl -X POST "http://localhost:8004/chat/channels/" \
-H "Content-Type: application/json" \
-d '{"name": "General Chat", "member_ids": [1, 2]}'
# Send a message
curl -X POST "http://localhost:8004/chat/channels/1/messages/" \
-H "Content-Type: application/json" \
-d '{"sender_id": 1, "body": "Hello everyone!"}'
# Mark message as read
curl -X POST "http://localhost:8004/chat/messages/1/mark-read/"
# Check user presence
curl -X GET "http://localhost:8004/chat/presence/1/"The application uses SQLite with the following tables:
- users: User information (id, email, name, created_at)
- partner_requests: Partner requests (id, sender_id, recipient_id, status, created_at)
- partnerships: Created partnerships (id, user_a_id, user_b_id, created_at)
- chat_channels: Chat channels (id, name, created_at)
- channel_members: Many-to-many relationship between channels and users
- messages: Chat messages (id, sender_id, channel_id, body, is_read, created_at)
The database file (dealnest.db) is created automatically when the application starts.
The application uses environment variables for configuration. A .env.example file is provided as a template:
# Application Settings
APP_ENV=development
APP_PORT=8004
LOG_LEVEL=INFO
# Database Configuration
DATABASE_URL=sqlite:///./dealnest.db
# Email Configuration (for future production use)
EMAIL_SERVICE_URL=
EMAIL_API_KEY=
EMAIL_FROM_ADDRESS=noreply@dealnest.com
# Redis Configuration (for future caching)
REDIS_URL=redis://localhost:6379
# Security (for future authentication)
SECRET_KEY=your-secret-key-here-change-in-production
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=30Copy .env.example to .env and modify the values as needed for your environment.
A complete HTML/JavaScript demo is included to showcase the real-time chat functionality:
-
Start the API server:
poetry run python -m app.main
-
Open the demo: Open
static/chat_demo.htmlin your browser -
Features demonstrated:
- Connect as different users via WebSocket
- Create and join chat channels
- Send real-time messages
- See presence status (online/offline)
- Receive read receipts
- View event logs for debugging
The demo includes a modern UI with connection status, message history, presence indicators, and real-time event logging.
Run the test suite:
poetry run pytest tests/ -vThe tests cover:
- User creation and retrieval
- Partner request creation and validation
- Request acceptance and rejection
- Chat channel creation and management
- Real-time messaging functionality
- Presence tracking
- Read receipts
- Error handling for duplicate requests and invalid actions
The application includes a mock email notification system that logs notifications to the console. When:
- A partner request is created: Recipient receives notification
- A partner request is accepted: Sender receives notification
Example notification log:
π§ EMAIL NOTIFICATION: To: Bob
π§ EMAIL NOTIFICATION: Subject: New Partner Request
π§ EMAIL NOTIFICATION: Body: You have a new partner request from Alice.
π§ EMAIL NOTIFICATION: Timestamp: 2024-01-15 10:30:00
π§ EMAIL NOTIFICATION: Status: Sent (mocked)
dealnest-api/
βββ app/
β βββ api/
β β βββ schemas.py # Pydantic models for API validation
β β βββ users.py # User endpoints
β β βββ partner_requests.py # Partner request endpoints
β βββ core/
β β βββ config.py # Application configuration
β β βββ logging.py # Logging configuration
β βββ db/
β β βββ database.py # Database configuration
β β βββ models.py # SQLAlchemy models
β βββ services/
β β βββ notification_service.py # Email notification service
β βββ main.py # FastAPI application entry point
βββ tests/
β βββ test_users.py # User endpoint tests
β βββ test_partner_requests.py # Partner request tests
βββ pyproject.toml # Poetry dependencies
βββ README.md # This file
- User Model: Simple stub with id, email, name, and created_at timestamp
- PartnerRequest Model: Links sender and recipient with status tracking
- Partnership Model: Created when requests are accepted, represents the partnership relationship
- Partner requests start as "pending"
- Can transition to "accepted" or "rejected"
- Once responded to, status cannot be changed again
- Mock email service logs notifications to console
- Notifications sent for request creation and acceptance
- Easy to replace with real email service in production
- Comprehensive validation for all endpoints
- Prevents duplicate requests between same users
- Prevents self-requests
- Validates user existence before operations
For handling thousands of requests per second, consider:
-
Database Optimization:
- Use PostgreSQL or MySQL instead of SQLite
- Add database indexes on frequently queried fields
- Implement connection pooling
-
Caching:
- Cache user data and request statuses
- Use Redis for session management
-
Background Processing:
- Move email notifications to background queues (Celery/RQ)
- Use message brokers for async processing
-
API Optimization:
- Implement pagination for large result sets
- Add rate limiting
- Use async/await throughout the application
-
Monitoring:
- Add application metrics and monitoring
- Implement health checks and alerting
- Use structured logging
The application includes a health check endpoint:
curl -X GET "http://localhost:8004/health"This returns {"status": "ok"} when the application is running properly.