Protean FastAPI Server
The Protean framework provides a built-in FastAPI server that allows you to quickly expose your domain through a REST API. This guide covers how to start, access, and customize the server for your application.
Starting the Server
Protean provides a CLI command called server
that starts a FastAPI server. You can run it from the command line:
protean server --domain=path/to/domain --port=8000
Command Parameters
Parameter | Description | Default |
---|---|---|
--domain |
Path to the domain | . (current directory) |
--host |
Host to bind to | 0.0.0.0 |
--port |
Port to bind to | 8000 |
--debug |
Enable debug mode | False |
--cors |
Enable CORS | True |
--cors-origins |
Comma-separated list of allowed CORS origins | * |
Domain Discovery
The --domain
parameter can be specified in several formats:
- Module in current folder:
--domain=my_domain
- Module in a subfolder:
--domain=src/my_domain
- Module string:
--domain=my_package.my_domain
- Specific instance:
--domain=my_domain:app2
The server attempts to locate your domain in the following order:
- Check the
PROTEAN_DOMAIN
environment variable (if set) - Use the path provided in the
--domain
parameter - Look for a
domain.py
orsubdomain.py
file in the current directory
When a module is found, the server looks for a domain in the following order:
- Variable named
domain
orsubdomain
- Any variable that is an instance of
Domain
- If multiple instances are found, an error is raised
Example:
# Using a specific module
protean server --domain=my_app.domain
# Using a specific instance in a module
protean server --domain=my_app.domain:my_domain_instance
# Using environment variable (alternative)
export PROTEAN_DOMAIN=my_app.domain
protean server
Accessing the FastAPI Server
Once the server is running, you can access the root endpoint at http://localhost:8000/
(or whatever host and port you've configured). This endpoint returns basic information about your domain:
{
"status": "success",
"message": "Protean API server running with domain: YourDomainName",
"data": {
"domain": {
"name": "YourDomainName",
"normalized_name": "your_domain_name"
}
}
}
Customizing the FastAPI App
The Protean server is built on FastAPI, which means you can leverage all FastAPI features for your API. You can customize the FastAPI application using the create_app
factory function:
from protean.server.fastapi_server import create_app
from protean.utils.domain_discovery import derive_domain
# Get your domain
domain = derive_domain("./my_domain")
# Create the FastAPI app
app = create_app(
domain=domain,
debug=True,
enable_cors=True,
cors_origins=["http://localhost:3000"]
)
# Add custom routes, middleware, etc.
@app.get("/custom")
async def custom_endpoint():
return {"message": "Custom endpoint"}
# Add custom middleware
@app.middleware("http")
async def custom_middleware(request, call_next):
# Do something before the request is processed
response = await call_next(request)
# Do something after the request is processed
return response
# Run with uvicorn
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
This approach gives you full control over the FastAPI application while still ensuring the Protean domain context is properly set up.
Server Functionality
The Protean FastAPI server provides several important functions:
-
Domain Context: The server sets up a domain context for each request, ensuring that domain operations execute in the correct context.
-
CORS Support: Built-in CORS middleware that can be configured based on your application's needs.
-
API Documentation: Since it's built on FastAPI, you automatically get interactive API documentation at
/docs
and/redoc
endpoints. -
Error Handling: The server provides consistent error responses for domain exceptions.
Advanced Configuration
For more advanced use cases, you might want to configure logging, add authentication middleware, or integrate with other FastAPI extensions. These can all be accomplished by accessing the underlying FastAPI application.
Event Handling and Message Processing
The Protean server plays a crucial role in the event-driven architecture by managing subscriptions and processing messages:
Subscription Management
When the server starts, it automatically:
-
Collects Subscriptions: The server scans your domain for defined event and command handlers.
-
Initializes Subscribers: Each handler is initialized as a polling subscriber and registered with the event store.
-
Manages Subscription Lifecycle: The server handles the lifecycle of subscriptions, including starting, stopping, and error handling.
Event Store Polling
The server continuously polls the event store for new messages:
-
Command Processing: Incoming commands are routed to their appropriate handlers.
-
Event Handling: Domain events are distributed to all interested handlers.
-
Message Ordering: Messages are processed in the order they were published to maintain consistency.
Configuring Subscription Behavior
You can configure how subscriptions work through your domain configuration:
# Example domain configuration
domain = Domain(
name="example",
# Configure event store and its subscriptions
config={
"event_store": {
"provider": "message_db",
"database_uri": "postgresql://message_store@localhost:5433/message_store",
"polling_interval": 1.0, # Poll interval in seconds
"max_retry_count": 3, # Number of retries for failed processing
}
}
)