TASK
Implementation
API composition (aggregation) enables clients to fetch data from multiple services with a single request. The gateway fans out to backends and composes the response.
Composition patterns:
1. Aggregation (merge results):
Client → Gateway → [Service A, Service B, Service C]
Gateway merges: {a: {...}, b: {...}, c: {...}}
2. Composition (transform and combine):
Client → Gateway → [User Service, Order Service]
Gateway composes: {user: {...}, orders: [...]}
3. Chaining (sequential calls):
Client → Gateway → Service A → (use A's result) → Service BExample: Order details aggregation:
// Client request:
Request: {"type": "api_request", "msg_id": 1, "method": "GET", "path": "/api/orders/123/details"}
// Gateway fans out to 3 services:
Service A (Orders): GET /orders/123 → {"id": 123, "user_id": 456, "items": [...]}
Service B (Users): GET /users/456 → {"id": 456, "name": "Alice", "email": "..."}
Service C (Products): GET /products?id=1,2,3 → [{"id": 1, "name": "Widget"}, ...]
// Gateway composes response:
Response: {"type": "api_response", "in_reply_to": 1, "body": {
"order": {"id": 123, "items": [...]},
"user": {"id": 456, "name": "Alice"},
"products": [{"id": 1, "name": "Widget"}, ...]
}}Aggregation configuration:
{
"aggregations": {
"/api/orders/*/details": {
"backend_requests": [
{"service": "orders", "path_template": "/orders/{order_id}"},
{"service": "users", "path_template": "/users/{user_id}", "source": "orders.user_id"},
{"service": "products", "path_template": "/products", "source": "orders.items.*.product_id"}
],
"response_template": {
"order": "$.orders",
"user": "$.users",
"products": "$.products"
},
"timeout_ms": 2000,
"failure_strategy": "partial" // or "fail_fast"
}
}
}Failure strategies:
partial: Return successful services, null for failed
{"order": {...}, "user": null, "products": [...]}
fail_fast: If any service fails, return error immediately
{"error": "Service unavailable: users-service"}
ignore: Continue without failed service
{"order": {...}, "products": [...]}Sample Test Cases
Aggregate from 3 servicesTimeout: 5000ms
Input
{"src":"client","dest":"gateway","body":{"type":"init","msg_id":1,"aggregations":{"/api/orders/*/details":{"backends":["orders","users","products"]}}}}
{"src":"client","dest":"gateway","body":{"type":"api_request","msg_id":2,"method":"GET","path":"/api/orders/123/details"}}
Expected Output
{"src": "gateway", "dest": "client", "body": {"type": "init_ok", "in_reply_to": 1}}
Partial failure handlingTimeout: 5000ms
Input
{
"src": "client",
"dest": "gateway",
"body": {
"type": "api_request",
"msg_id": 1,
"method": "GET",
"path": "/api/orders/123/details"
},
"failure_strategy": "partial",
"failed_services": [
"users"
]
}Expected Output
{"src": "gateway", "dest": "client", "body": {"type": "api_response", "in_reply_to": 1, "body": {"order": {...}, "user": null, "products": [...]}}}
Hints
Hint 1▾
Gateway fans out requests to multiple backend services
Hint 2▾
Collect responses from all services
Hint 3▾
Merge/compose data into a single response for client
Hint 4▾
Execute requests in parallel for performance
Hint 5▾
Handle partial failures: return partial data or fail-fast
OVERVIEW
Theoretical Hub
Concept overview coming soon
Key Concepts
API compositionaggregation patterndata compositionparallel requestsbackend fan-outresponse merging
main.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3
import sys
import json
def main():
# Your implementation here
for line in sys.stdin:
msg = json.loads(line)
print(json.dumps(msg), flush=True)
if __name__ == "__main__":
main()