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.6.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.6-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mmar_pyhr-0.0.6.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.6.tar.gz
Algorithm Hash digest
SHA256 4336323aa5f551b202a0fcdfab0189c5a3af864b1613c79f6272973fe4c157b3
MD5 4a7f2abeaef079f0ddf89049954865f0
BLAKE2b-256 b587fd6c277f6c60893b2422fad916d24d71dd83db9d83a6328303d8f0044d09

See more details on using hashes here.

File details

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

File metadata

  • Download URL: mmar_pyhr-0.0.6-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.6-py3-none-any.whl
Algorithm Hash digest
SHA256 edf14174b616b45a684fdbcaede1a975cc2328c9771ea64ada891c2df5239568
MD5 69a802439c4afdfdcbae9c9bd24c7f0d
BLAKE2b-256 436c1853e0ecc18fde8cf35b9d4640477bc89d50a5d7d9b7e2410f23efb11b45

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