Client Development¶
Build robust, production-ready plugin clients with comprehensive guides covering setup, resilience, and advanced patterns.
๐ค AI-Generated Content
This documentation was generated with AI assistance and is still being audited. Some, or potentially a lot, of this information may be inaccurate. Learn more.
Quick Start¶
import asyncio
from pyvider.rpcplugin import plugin_client
from calculator_pb2_grpc import CalculatorStub
from calculator_pb2 import AddRequest
async def main():
async with plugin_client(command=["python", "calculator.py"]) as client:
await client.start()
stub = CalculatorStub(client.grpc_channel)
result = await stub.Add(AddRequest(a=5, b=3))
print(f"Result: {result.result}")
if __name__ == "__main__":
asyncio.run(main())
Documentation Structure¶
Client Development Guide¶
Core Topics: - Quick start and basic setup - Client architecture and lifecycle - Configuration patterns (client vs plugin) - Context managers and manual lifecycle - Advanced patterns (multi-plugin, connection pooling) - Best practices and troubleshooting
Perfect for: Getting started, understanding fundamentals, basic configuration
Connection Resilience¶
Core Topics: - Exception handling and error hierarchy - Retry strategies (exponential backoff, jitter, circuit breaker) - Connection management and health monitoring - Auto-reconnection patterns - Connection pooling and load balancing - Best practices for fault-tolerant clients
Perfect for: Building production-ready, fault-tolerant clients
Direct Connections¶
Core Topics: - Connecting to existing servers (TCP, Unix sockets) - Environment-based configuration - Load balancing across multiple servers - mTLS security for direct connections - Service discovery integration - Best practices for microservices
Perfect for: Microservices, distributed systems, container deployments
Learning Paths¶
Goal: Build your first working plugin client
- Client Guide: Quick Start
- Client Guide: Client Patterns
- Client Guide: Configuration
- Examples: Quick Start
- Examples: Echo Service
Next: Add error handling and retry logic
Goal: Build resilient, production-ready clients
- Resilience: Exception Handling
- Resilience: Retry Strategies
- Resilience: Connection Management
- Client Guide: Advanced Patterns
- Configuration Guide
Next: Implement advanced patterns for microservices
Goal: Master distributed systems and microservices patterns
- Direct Connections
- Resilience: Circuit Breaker
- Resilience: Connection Pooling
- Security: mTLS
- Advanced Topics
Next: Implement service mesh integration
Common Patterns¶
Basic Client with Retry¶
async def robust_client():
max_retries = 3
for attempt in range(max_retries):
try:
async with plugin_client(command=["python", "plugin.py"]) as client:
await client.start()
stub = CalculatorStub(client.grpc_channel)
result = await stub.Add(AddRequest(a=5, b=3))
return result
except (TransportError, HandshakeError) as e:
if attempt < max_retries - 1:
delay = 2 ** attempt
logger.warning(f"Retry in {delay}s (attempt {attempt + 1}/{max_retries})")
await asyncio.sleep(delay)
else:
raise
See Connection Resilience for comprehensive retry patterns.
Direct Connection to Existing Server¶
async def connect_to_service():
# Connect to running server (no subprocess)
client = await plugin_client(
host="plugin-service.internal",
port=50051,
skip_subprocess=True
)
try:
stub = CalculatorStub(client.grpc_channel)
result = await stub.Add(AddRequest(a=10, b=5))
return result
finally:
await client.close()
See Direct Connections for microservices patterns.
Connection Pool for High Performance¶
from pyvider.rpcplugin import plugin_client
class ClientPool:
def __init__(self, command: list[str], size: int = 5):
self.command = command
self.size = size
self.connections = []
async def initialize(self):
for _ in range(self.size):
client = plugin_client(command=self.command)
await client.start()
self.connections.append(client)
async def acquire(self):
# Return available connection
return self.connections.pop() if self.connections else None
async def release(self, client):
# Return to pool
self.connections.append(client)
See Connection Resilience for complete implementation.
Related Documentation¶
- Server Development - Build plugin servers
- Security Guide - mTLS and authentication
- Configuration Guide - Environment-driven configuration
- Advanced Topics - Observability, performance tuning
- Examples - Complete working examples
Next Steps¶
- Read Client Development Guide - Understand fundamentals
- Study Connection Resilience - Add fault tolerance
- Explore Examples - See complete implementations
- Review Security Guide - Secure your clients