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.4.tar.gz (9.1 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.4-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for mmar_pyhr-0.0.4.tar.gz
Algorithm Hash digest
SHA256 e7b958f47a1e249def2d8eb8638ab3590be991f2f4956da712646c2db1d48b0a
MD5 f829d2b5e9d64a1163a7ef854ef55d1d
BLAKE2b-256 4e36d310d7aad8e76018680d9df17e7dcbf838bd98162e1aff141ce6397a5e83

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for mmar_pyhr-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 129ac71a0c5fbf4a303a194c5c97e2132a5a19f71862d383062d64852f09ec8c
MD5 bb7d4dc3d642f12deedf2a3a1c1319f3
BLAKE2b-256 64d04dcd29bca24144cb66cb1d4fb8d6c7e4d4990dd54f6b5e56672d9036efb0

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