Skip to main content

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_id support 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

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

mmar_pyhr-0.0.7.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mmar_pyhr-0.0.7-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file mmar_pyhr-0.0.7.tar.gz.

File metadata

  • Download URL: mmar_pyhr-0.0.7.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.31

File hashes

Hashes for mmar_pyhr-0.0.7.tar.gz
Algorithm Hash digest
SHA256 a5143385ca3730463d54ddf7447296117c05362df3fc4f4f0e867272680d54fc
MD5 d3a6c813b942f7d6dbb5281c23c77003
BLAKE2b-256 41db386c5a51777aebba3ea82d511bf443eb0125e8b5417273163ec693736405

See more details on using hashes here.

File details

Details for the file mmar_pyhr-0.0.7-py3-none-any.whl.

File metadata

  • Download URL: mmar_pyhr-0.0.7-py3-none-any.whl
  • Upload date:
  • Size: 11.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.31

File hashes

Hashes for mmar_pyhr-0.0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 15f756e7b8b8008de3b27323bf98f0981577fcae74a57b9020d9cee347dd03fc
MD5 d906785370836c83189cdd052c56efab
BLAKE2b-256 75fb2e1c8af845a0072e6ddf7a3381d0b653a31221d8e1871cdaf6c1904bc59d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page