Orchestrator service that coordinates atomic microservices, handles Pub/Sub subscriptions, and provides unified API endpoints.
The Composite Service acts as the central orchestrator for the microservices architecture:
- Routes requests to appropriate atomic services (Users, Events, Feed)
- Handles Pub/Sub message consumption for email notifications
- Provides composite endpoints (e.g., user feed with events and posts)
- Manages GraphQL API
- Coordinates cross-service operations
API Gateway β Composite Service β Atomic Services
β
Pub/Sub Subscriptions
β
Email Notifications
- Port: 8004
- Authentication: Trusts
x-firebase-uidheader from API Gateway - Pub/Sub: Subscribes to
event-createdanduser-createdtopics
- Python 3.9+
- Firebase service account key
- Google Cloud Pub/Sub (for email notifications)
- SMTP server credentials (for email sending)
-
Install dependencies
pip install -r requirements.txt
-
Configure environment variables Create a
.envfile:# Service URLs USERS_SERVICE_URL=http://localhost:8001 EVENTS_SERVICE_URL=http://localhost:8002 FEED_SERVICE_URL=http://localhost:8003 # GCP Configuration GCP_PROJECT_ID=your-project-id GOOGLE_CLOUD_PROJECT=your-project-id # Pub/Sub Topics PUBSUB_EVENT_CREATED_TOPIC=event-created PUBSUB_USER_CREATED_TOPIC=user-created # Pub/Sub Subscriptions PUBSUB_EVENT_NOTIFICATION_SUB=event-notification-sub PUBSUB_USER_WELCOME_SUB=user-welcome-sub # SMTP Configuration SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=your-email@gmail.com SMTP_PASS=your-app-password SMTP_FROM=your-email@gmail.com # Firebase FIREBASE_SERVICE_ACCOUNT_PATH=./serviceAccountKey.json
-
Add Firebase service account key
- Download from Firebase Console
- Place as
serviceAccountKey.jsonin service directory
-
Set up Pub/Sub topics and subscriptions See README_PUBSUB.md for detailed instructions.
-
Run the service
uvicorn main:app --host 0.0.0.0 --port 8004
The service will automatically start Pub/Sub subscribers in background threads.
| Variable | Description | Default | Required |
|---|---|---|---|
USERS_SERVICE_URL |
Users Service URL | http://localhost:8001 |
Yes |
EVENTS_SERVICE_URL |
Event Service URL | http://localhost:8002 |
Yes |
FEED_SERVICE_URL |
Feed Service URL | http://localhost:8003 |
Yes |
GCP_PROJECT_ID |
GCP project ID | - | Yes |
GOOGLE_CLOUD_PROJECT |
Same as GCP_PROJECT_ID | - | Yes |
PUBSUB_EVENT_CREATED_TOPIC |
Pub/Sub topic name | event-created |
No |
PUBSUB_USER_CREATED_TOPIC |
Pub/Sub topic name | user-created |
No |
PUBSUB_EVENT_NOTIFICATION_SUB |
Pub/Sub subscription name | event-notification-sub |
No |
PUBSUB_USER_WELCOME_SUB |
Pub/Sub subscription name | user-welcome-sub |
No |
SMTP_HOST |
SMTP server host | - | Yes (for emails) |
SMTP_PORT |
SMTP server port | 587 |
No |
SMTP_USER |
SMTP username | - | Yes (for emails) |
SMTP_PASS |
SMTP password | - | Yes (for emails) |
SMTP_FROM |
From email address | - | Yes (for emails) |
FIREBASE_SERVICE_ACCOUNT_PATH |
Path to Firebase service account JSON | ./serviceAccountKey.json |
No |
Get personalized feed for current user (events + posts)
Query Parameters:
skip_posts: Number of posts to skip (default: 0)limit_posts: Number of posts to return (default: 5, max: 100)skip_events: Number of events to skip (default: 0)limit_events: Number of events to return (default: 5, max: 100)
Response:
{
"user_id": 1,
"events": [
{
"event_id": 1,
"title": "Tech Meetup",
"start_time": "2024-01-15T18:00:00",
...
}
],
"posts": [
{
"post_id": 1,
"title": "My Post",
"created_at": "2024-01-01T00:00:00",
...
}
]
}The Composite Service proxies requests to atomic services:
/api/users/*β Users Service/api/events/*β Event Service/api/posts/*β Feed Service/api/friends/*β Users Service (friend management)
All requests are forwarded with the x-firebase-uid header.
GraphQL API endpoint
Query Example:
query {
users {
user_id
username
email
}
events {
event_id
title
location
}
}See graphql_api/schema.py for available queries and mutations.
The service subscribes to two Pub/Sub topics:
-
event-notification-sub(subscribes toevent-createdtopic)- Triggered when a new event is created
- Sends email notification to event creator
-
user-welcome-sub(subscribes touser-createdtopic)- Triggered when a new user is created
- Sends welcome email to new user
Event Service β Publishes to "event-created" topic
β
Composite Service β Consumes message
β
Email Service β Sends notification email
Subscribers start automatically when the service starts:
# In main.py
start_event_subscriber()
start_user_subscriber()The service includes email functionality for:
- Event creation notifications
- User welcome emails
SMTP Configuration:
- Supports Gmail, Outlook, and other SMTP servers
- Uses TLS/STARTTLS for secure connections
- Requires app-specific password for Gmail
This service does not perform Firebase authentication directly. It:
- Receives
x-firebase-uidheader from API Gateway - Forwards this header to atomic services
- Uses
firebase_uidfromrequest.state(set by API Gateway middleware)
docker build -t composite-service .docker run -p 8004:8004 \
-e USERS_SERVICE_URL=http://users-service:8001 \
-e EVENTS_SERVICE_URL=http://event-service:8002 \
-e FEED_SERVICE_URL=http://feed-service:8003 \
-e GCP_PROJECT_ID=your-project-id \
-e SMTP_HOST=smtp.gmail.com \
-e SMTP_USER=your-email@gmail.com \
-e SMTP_PASS=your-app-password \
composite-serviceThe service is deployed to Cloud Run with:
- VPC Connector for accessing VM services
- Pub/Sub subscriber permissions
- Environment variables configured via deployment script
- Background threads for Pub/Sub subscribers
See ../GCP_DEPLOYMENT_GUIDE.md for details.
curl http://localhost:8004/curl -H "x-firebase-uid: your-firebase-uid" \
"http://localhost:8004/api/users/me/feed?limit_posts=10&limit_events=10"python debug_pubsub.pyfrom email_service import send_email
send_email(
to="test@example.com",
subject="Test Email",
body="This is a test email"
)Interactive API documentation available at:
- Swagger UI:
http://localhost:8004/docs - ReDoc:
http://localhost:8004/redoc - OpenAPI JSON:
http://localhost:8004/openapi.json - GraphQL Playground:
http://localhost:8004/graphql(if enabled)
The service returns standard HTTP status codes:
200 OK: Successful request400 Bad Request: Invalid request data401 Unauthorized: Missing or invalidx-firebase-uidheader404 Not Found: Resource not found502 Bad Gateway: Downstream service unavailable500 Internal Server Error: Server error
- Service Orchestration: Routes requests to appropriate atomic services
- Pub/Sub Integration: Event-driven email notifications
- Composite Endpoints: Unified endpoints combining multiple services
- GraphQL API: Flexible querying of data
- Error Handling: Graceful handling of downstream service failures
- Request Forwarding: Maintains authentication headers across services
- Pub/Sub subscribers run in background threads and persist for the service lifetime
- Email service uses synchronous SMTP connections
- Service URLs can point to Cloud Run URLs or VM private IPs
- The service acts as a reverse proxy for atomic services
- Pub/Sub Setup Guide - Detailed Pub/Sub configuration
- GraphQL Schema - GraphQL API schema
When adding new endpoints:
- Add route to
routers/composite_router.py - Use
request.state.firebase_uidfor user identification - Forward requests to atomic services using
forward_request()helper - Add proper error handling
- Update this README with endpoint documentation