RPC API Reference
Complete API reference for the RPC subsystem — RPCRegistry, RPCProxy, ServiceProxy, Microservice descriptor, exception classes, and data models.
This page documents every class in the microservices.__base.rpc package and the Microservice descriptor. All signatures are taken directly from the source code.
RPCRegistry
microservices.__base.rpc.registry.RPCRegistry
Singleton registry for RPC-exposed services. Stores local service instances and remote service specs discovered from Redis.
Constructor
Takes no parameters. Initializes empty _local and _remote dictionaries.
Methods
| Method | Parameters | Return Type | Description |
|---|---|---|---|
register(name, instance, path_segments) | name: str, instance: Any, path_segments: list[str] | None | Register a local service for RPC. Introspects the instance to extract HTTP endpoint methods, their parameter signatures, and builds MethodMeta entries. |
generate_spec() | (none) | dict[str, Any] | Generate an OpenAPI-like spec for all locally registered RPC services. Returns {"rpc_version": "1.0", "base_url": "...", "services": {...}}. |
generate_spec_for(name) | name: str | Optional[dict[str, Any]] | Generate spec for a single service by name. Returns None if not found. |
publish_to_redis(ttl) | ttl: int = 60 | None | Async. Publish local RPC specs to shared Redis. Each service is published individually under singularity:rpc:services:{name} and the full spec under singularity:rpc:spec, both with the given TTL in seconds. |
remove_from_redis() | (none) | None | Async. Remove all local RPC specs from shared Redis. |
discover_remote() | (none) | None | Async. Scan Redis for all singularity:rpc:services:* keys and register any services not already in _local as RemoteServiceEntry instances. |
discover_single_service(service_name) | service_name: str | bool | Async. Discover a single remote service from Redis on-demand. Returns True if found (locally or remotely), False otherwise. |
get_proxy(caller) | caller: str | RPCProxy | Get an RPC proxy bound to a caller identity. |
The registry uses settings.celery_broker_url as the Redis connection URL for publishing and discovery. Ensure your Redis instance is accessible.
RPCClient
microservices.__base.rpc.client.RPCClient
The public RPC interface. The module-level rpc singleton is an instance of this class.
Usage Patterns
from singularity.rpc import rpc
# Pattern 1: Direct proxy call
result = await rpc("orders").payments.charge(user_id="u1", amount=9.99)
# Pattern 2: Class-level descriptor for dependency declaration
class MyService:
payments = rpc.remote("payments")
async def checkout(self):
result = await self.payments.charge(user_id="u1", amount=9.99)Methods
| Method | Parameters | Return Type | Description |
|---|---|---|---|
__call__(caller) | caller: str | RPCProxy | Get an RPC proxy bound to the given caller identity. |
remote(service_name) | service_name: str | RemoteServiceDescriptor | Declare a remote service dependency as a class-level attribute. Returns a descriptor that resolves to a ServiceProxy at access time. |
Module-Level Functions
| Function | Parameters | Return Type | Description |
|---|---|---|---|
rpc | (singleton) | RPCClient | Pre-created module-level singleton. Import and call directly. |
get_registry() | (none) | RPCRegistry | Get the module-level RPC registry singleton. Used internally by the Manager. |
RPCProxy
microservices.__base.rpc.proxy.RPCProxy
Proxy bound to a caller identity. Attribute access returns a ServiceProxy for the target service.
Constructor
| Parameter | Type | Description |
|---|---|---|
caller | str | The name of the calling service |
registry | RPCRegistry | The RPC registry instance |
Access Patterns
| Pattern | Returns | Description |
|---|---|---|
proxy.payments | ServiceProxy | Dot access for standard service names |
proxy["my-service"] | ServiceProxy | Bracket access for names with hyphens or special characters |
ServiceProxy
microservices.__base.rpc.proxy.ServiceProxy
Proxy for a specific target service. Method calls are dispatched locally (in-process) or remotely (HTTP) with blacklist enforcement.
Constructor
| Parameter | Type | Description |
|---|---|---|
service_name | str | The target service name |
caller | str | The calling service name |
registry | RPCRegistry | The RPC registry instance |
Dispatch Behavior
When you access a method on a ServiceProxy, it resolves using this priority:
- Local -- If
service_nameexists inregistry._local, checks the blacklist, verifies the method exists, and returns the method directly (in-process call). - Remote (cached) -- If
service_nameexists inregistry._remote, checks the blacklist, verifies the method exists, and returns an async callable that makes an HTTP request. - Remote (lazy discovery) -- If the service is not found locally or in the cache, returns an async callable that first attempts
discover_single_service()from Redis, then dispatches the HTTP call.
Remote Call Details
| Aspect | Value |
|---|---|
| HTTP Client | httpx.AsyncClient |
| Timeout | 30.0 seconds |
| Custom Header | X-RPC-Caller: {caller} |
| Request Method | Determined by the remote method spec (GET, POST, etc.) |
Internal Methods
| Method | Parameters | Return Type | Description |
|---|---|---|---|
_check_blacklist(blacklist) | blacklist: list[str] | None | Raises RPCAccessDenied if the caller is in the blacklist. |
RemoteServiceDescriptor
microservices.__base.rpc.proxy.RemoteServiceDescriptor
Python descriptor for class-level remote service declaration. Used by rpc.remote().
Constructor
| Parameter | Type | Description |
|---|---|---|
service_name | str | The target service name |
Descriptor Protocol
When accessed on an instance, __get__ reads the _service_name attribute (injected by the Manager) and returns a ServiceProxy via rpc(caller)[service_name].
Microservice
microservices.__base.microservice.Microservice
Base class for declaring remote microservice dependencies. Uses the Python descriptor protocol to bind to the caller identity at access time.
Class Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
host_url | str | "" | Base URL of the remote deployment (e.g. "http://localhost:8001") |
api_key | str | "" | API key sent as X-API-Key header (optional) |
timeout | float | 30.0 | Request timeout in seconds |
service_name | str | "" | If set, binds directly to this service (skips repo-level proxy). If empty, returns a MicroserviceProxy for multi-service access. |
Descriptor Behavior
service_name | __get__ Returns | Usage Pattern |
|---|---|---|
"" (empty) | MicroserviceProxy | self.billing.invoice.post(...) -- pick service, then method |
"test" (set) | MicroserviceServiceProxy | self.test.get(...) -- call method directly |
Usage Example
from singularity.microservices.microservice import Microservice
from singularity.config import settings
class BillingMS(Microservice):
host_url = settings.billing_host_url
api_key = settings.billing_api_key
timeout = 10
class OrdersService:
billing = BillingMS()
async def checkout(self, order_id: str):
result = await self.billing.invoice.post(order_id=order_id)
return resultMicroserviceProxy
microservices.__base.rpc.proxy.MicroserviceProxy
Proxy representing a remote deployment, bound to a caller identity. Attribute access returns a MicroserviceServiceProxy for the named service.
Constructor
| Parameter | Type | Description |
|---|---|---|
host_url | str | Base URL of the remote deployment |
api_key | str | API key for authentication |
timeout | float | Request timeout in seconds |
caller | str | The calling service name |
Access Patterns
| Pattern | Returns | Description |
|---|---|---|
proxy.invoice | MicroserviceServiceProxy | Dot access for service names |
proxy["my-service"] | MicroserviceServiceProxy | Bracket access for names with hyphens |
MicroserviceServiceProxy
microservices.__base.rpc.proxy.MicroserviceServiceProxy
Proxy for a specific service on a remote deployment. Method calls are dispatched via convention-based URL construction.
Constructor
| Parameter | Type | Description |
|---|---|---|
service_name | str | The target service name |
host_url | str | Base URL of the remote deployment |
api_key | str | API key for authentication |
timeout | float | Request timeout in seconds |
caller | str | The calling service name |
Method Name Convention
Method names on this proxy are resolved to HTTP endpoints using the following convention (matching the Manager's route registration):
| Method Name | HTTP Method | URL |
|---|---|---|
get | GET | {host_url}/api/{service_name} |
post | POST | {host_url}/api/{service_name} |
get_example | GET | {host_url}/api/{service_name}/example |
post_order_payment | POST | {host_url}/api/{service_name}/order_payment |
Remote Call Details
| Aspect | Value |
|---|---|
| HTTP Client | httpx.AsyncClient |
| Timeout | Value from Microservice.timeout |
| Headers | X-RPC-Caller: {caller}, X-API-Key: {api_key} (if set) |
Exception Classes
microservices.__base.rpc.exceptions
All RPC exceptions inherit from RPCError, which inherits from Python's built-in Exception.
Exception Hierarchy
Exception Details
| Exception | Constructor Parameters | Fields | When Raised |
|---|---|---|---|
RPCError | (standard Exception args) | message | Base class; not raised directly |
RPCServiceNotFound | service: str | service | Target service not found in local or remote registry |
RPCMethodNotFound | service: str, method: str | service, method | Method not found on the target service |
RPCAccessDenied | caller: str, target: str | caller, target | Caller is in the target service's blacklist |
RPCServiceUnavailable | service: str, url: str, detail: str = "" | service | Remote HTTP connection failed or returned an error |
Error Messages
| Exception | Message Format |
|---|---|
RPCServiceNotFound | "RPC service not found: '{service}'" |
RPCMethodNotFound | "RPC method not found: '{service}.{method}'" |
RPCAccessDenied | "RPC access denied: '{caller}' is blacklisted from '{target}'" |
RPCServiceUnavailable | "RPC service '{service}' unavailable at '{url}': {detail}" |
Data Models
microservices.__base.rpc.models
Internal data classes used by the registry and proxy system.
MethodMeta
Metadata about an RPC-exposed method. Uses __slots__ for memory efficiency.
| Field | Type | Default | Description |
|---|---|---|---|
params | dict | (required) | Parameter metadata: {name: {"type": str, "required": bool}} |
return_type | str | (required) | String representation of the return type annotation |
description | str | (required) | First line of the method's docstring |
is_async | bool | (required) | Whether the method is a coroutine |
http_method | str | "POST" | HTTP method (GET, POST, PUT, DELETE, PATCH) |
sub_path | str | "" | Sub-path for http_exposed routes (e.g. "status" for get=status) |
LocalServiceEntry
A locally registered RPC service. Uses __slots__.
| Field | Type | Description |
|---|---|---|
instance | Any | The service instance |
methods | dict[str, MethodMeta] | Introspected method metadata |
blacklist | list[str] | Services blocked from calling this service |
endpoint_prefix | str | Full URL prefix (e.g. "http://localhost:8000/api/v1/payments") |
path_segments | list[str] | Directory path segments (e.g. ["v1", "payments"]) |
RemoteServiceEntry
A remotely discovered RPC service. Uses __slots__.
| Field | Type | Description |
|---|---|---|
base_url | str | Base URL of the remote deployment |
blacklist | list[str] | Services blocked from calling this service |
methods | dict[str, Any] | Method specs as raw dictionaries from Redis |
Service API Reference
Complete API reference for the service layer — Manager, Acquire, ServiceDiscovery, ServiceGenerator, BaseWebhook, and WebSocketManager.
Task API Reference
Complete API reference for the background task system — @task decorator, TaskWrapper, TaskRunner, notification channels, and WebhookConfig.