No project description provided
Project description
mmar-pyhr
Pydantic-HTTP-RPC - A lightweight RPC framework based on HTTP + FastAPI with Pydantic validation.
Overview
mmar-pyhr provides a simple RPC-style interface for service-to-service communication over HTTP, similar to mmar-ptag but using HTTP instead of gRPC. It was created to address Kubernetes compatibility issues with gRPC while maintaining the same developer-friendly interface.
Features
- Type-safe RPC using Pydantic for validation
- HTTP/JSON transport (Kubernetes-friendly, no service mesh required)
- Interface-based design using Python classes
- Built-in tracing with
trace_idsupport via HTTP headers - Health check endpoints for Kubernetes pod lifecycle management
- Smart address handling (port numbers, localhost, full URLs)
- Sync/async support for service methods
Installation
uv pip install mmar-pyhr
Quick Start
Server
from mmar_pyhr import PyhrServerConfig, deploy_pyhr_server
class UserService:
def get_user(self, *, user_id: int, trace_id: str = "") -> dict:
return {"id": user_id, "name": "John Doe"}
def create_user(self, *, name: str, email: str, trace_id: str = "") -> dict:
return {"id": 123, "name": name, "email": email}
if __name__ == "__main__":
config = PyhrServerConfig(port=8000, host="0.0.0.0")
deploy_pyhr_server(
config_server=config,
service=UserService()
)
Client
from mmar_pyhr import pyhr_client
class UserServiceI:
def get_user(self, *, user_id: int, trace_id: str = "") -> dict:
raise NotImplementedError
def create_user(self, *, name: str, email: str, trace_id: str = "") -> dict:
raise NotImplementedError
# Create client
client = pyhr_client(UserServiceI, "localhost:8000")
# Make requests
user = client.get_user(user_id=42)
new_user = client.create_user(name="Alice", email="alice@example.com")
# With trace_id
user = client.get_user(user_id=42, trace_id="req-123")
Address Formats
The client accepts various address formats:
pyhr_client(Service, 9494) # → http://localhost:9494
pyhr_client(Service, ":9494") # → http://localhost:9494
pyhr_client(Service, "localhost:9494") # → http://localhost:9494
pyhr_client(Service, "http://localhost:9494") # → http://localhost:9494
pyhr_client(Service, "https://api.example.com") # → https://api.example.com
API Routes
The server automatically creates the following routes:
RPC Endpoints
POST /api/{method_name} → service.method_name(**kwargs)
Health Checks
GET /health_check → {"status": "ok"}
GET /health/liveness → {"status": "alive"}
GET /health/readiness → {"status": "ready"}
Tracing
Trace IDs are automatically propagated via the X-Trace-ID HTTP header:
# Client
client.get_user(user_id=42, trace_id="req-123")
# Server automatically receives trace_id in context
# and can use it for logging
Transport Abstraction
mmar-pyhr integrates with the mmar-mimpl transport registry:
from mmar_mimpl import get_transport
# Uses MMAR_TRANSPORT environment variable
transport = get_transport() # "pyhr" or "mmar_pyhr"
# Create client
client = transport.make_client(UserServiceI, address="localhost:8000")
# Deploy server
transport.deploy_server(
service=UserService(),
config=None,
config_server=PyhrServerConfig(port=8000)
)
Set the transport via environment variable:
export MMAR_TRANSPORT=pyhr
# or
export MMAR_TRANSPORT=mmar_pyhr
Configuration
Client Configuration
from mmar_pyhr import PyhrTransportConfig
config = PyhrTransportConfig(
timeout=30.0, # Request timeout in seconds
retry_attempts=3, # Number of retry attempts
)
Server Configuration
from mmar_pyhr import PyhrServerConfig
config = PyhrServerConfig(
host="0.0.0.0", # Bind host
port=8000, # Bind port
max_workers=1, # Number of worker processes
log_level="info", # Logging level
)
Comparison with mmar-ptag
| Feature | mmar-ptag (gRPC) | mmar-pyhr (HTTP) |
|---|---|---|
| Transport | gRPC/HTTP2 | HTTP/JSON |
| Serialization | JSON over Protobuf | Pure JSON |
| Kubernetes | Requires service mesh | Native support |
| Debugging | Requires grpcurl | Standard curl/httpie |
| Health checks | Custom implementation | Built-in HTTP endpoints |
| Load balancing | Connection-level (needs mesh) | Request-level (native K8s) |
Development
# Run tests
uv run pytest
# Build package
uv build
License
MIT
See Also
- mmar-ptag - gRPC-based RPC framework
- Architecture Decision: gRPC to HTTP migration
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mmar_pyhr-0.0.2.tar.gz.
File metadata
- Download URL: mmar_pyhr-0.0.2.tar.gz
- Upload date:
- Size: 9.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.31
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee3e51fcda3ee76f8522510c9677dd31cf9189b5948ffa9580f4e48f21a275d4
|
|
| MD5 |
a20fe509fa994a0221ee119350bd78e7
|
|
| BLAKE2b-256 |
e34127a549813c0ca8264dc39c82c9233a675f9722c3979193d61a931eaf1136
|
File details
Details for the file mmar_pyhr-0.0.2-py3-none-any.whl.
File metadata
- Download URL: mmar_pyhr-0.0.2-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.5.31
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27a6c20813f94267a689dd68c3acf9f285d86cf54322ef29dbe966f685661f83
|
|
| MD5 |
15caf5efe3abd13d4c5dc122679a0c7b
|
|
| BLAKE2b-256 |
166238a8fcb645ef2ac0280f394abb0510796d32867af0c51346f1403363fab0
|