- Overview
- Architecture
- Components
- Creating a New Service
- Creating a New Client
- Common Schemas and Validation
- Error Handling
- Testing
- Common Issues and Solutions
- Best Practices
The Genesis Function Service system provides a distributed RPC (Remote Procedure Call) framework built on RTI Connext DDS. It enables creation of robust, type-safe services with automatic validation, error handling, and consistent patterns for both service and client implementations.
- OpenAI-style function schemas
- Built-in input validation
- Consistent error handling
- Automatic service discovery
- Asynchronous communication
- Comprehensive logging
- Resource cleanup
- Client initializes and waits for service discovery
- Service registers functions with schemas
- Client calls function with parameters
- Service validates inputs and processes request
- Service returns formatted response
- Client receives and processes response
- Uses RTI Connext DDS for communication
- Domain-based service discovery
- Quality of Service (QoS) profiles
- Reliable message delivery
- Publisher/Subscriber pattern
Base class for all services providing:
- Function registration
- Schema validation
- Request handling
- Response formatting
- Resource management
Base class for all clients providing:
- Service discovery
- Function calling
- Input validation
- Error handling
- Resource management
class YourService(GenesisRPCService):
def __init__(self):
super().__init__(service_name="YourServiceName")
# Get common schemas
text_schema = self.get_common_schema("text")
number_schema = self.get_common_schema("number")
# Register functions
self.register_function(
self.your_function,
"Function description",
{
"type": "object",
"properties": {
"param1": text_schema.copy(),
"param2": number_schema.copy()
},
"required": ["param1"],
"additionalProperties": False
},
operation_type="your_operation_type",
common_patterns={
"param1": {"type": "text", "min_length": 1},
"param2": {"type": "number", "minimum": 0}
}
)def your_function(self, param1: str, param2: Optional[float] = None) -> Dict[str, Any]:
# Log function call
logger.debug(f"SERVICE: your_function called with param1='{param1}', param2={param2}")
# Validate inputs
self.validate_text_input(param1, min_length=1)
if param2 is not None:
self.validate_numeric_input(param2, minimum=0)
# Process request
result = {
"processed": f"{param1}-{param2}"
}
# Return formatted response
return self.format_response(
{"param1": param1, "param2": param2},
result
)class YourClient(GenesisRPCClient):
def __init__(self):
super().__init__(service_name="YourServiceName")
# Add validation patterns
self.validation_patterns.update({
"custom_text": {
"min_length": 1,
"max_length": 100
},
"custom_number": {
"minimum": 0,
"maximum": 100
}
})async def your_function(self, param1: str, param2: Optional[float] = None) -> Dict[str, Any]:
# Log function call
logger.debug(f"CLIENT: Calling your_function with param1='{param1}', param2={param2}")
# Validate inputs
self.validate_text(param1, pattern_type="custom_text")
if param2 is not None:
self.validate_numeric(param2, pattern_type="custom_number")
# Call service function
return await self.call_function_with_validation(
"your_function",
param1=param1,
param2=param2
)-
text
- min_length: Minimum text length
- max_length: Maximum text length (optional)
- pattern: Regex pattern (optional)
-
number
- minimum: Minimum value
- maximum: Maximum value
- type: "integer" or "number"
-
letter
- min_length: 1
- max_length: 1
- pattern: "^[a-zA-Z]$"
-
count
- minimum: 0
- type: "integer"
# Text validation
self.validate_text_input(text, min_length=1, max_length=None, pattern=None)
# Numeric validation
self.validate_numeric_input(value, minimum=None, maximum=None)# Text validation
self.validate_text(text, pattern_type="custom_text")
# Numeric validation
self.validate_numeric(value, pattern_type="custom_number")
# Enum validation
self.validate_enum_value(value, pattern_type="custom_enum")-
ValueError
- Invalid input values
- Failed validation
- Out of range values
-
RuntimeError
- Service communication errors
- Unknown functions
- Processing errors
-
TimeoutError
- Service discovery timeout
- Function call timeout
try:
result = await client.your_function("test", 50)
except ValueError as e:
# Handle validation errors
logger.error(f"Validation error: {str(e)}")
except TimeoutError as e:
# Handle timeouts
logger.error(f"Timeout error: {str(e)}")
except RuntimeError as e:
# Handle service errors
logger.error(f"Service error: {str(e)}")
except Exception as e:
# Handle unexpected errors
logger.error(f"Unexpected error: {str(e)}", exc_info=True)- Start service in background
- Wait for initialization
- Run client tests
- Clean up resources
Example test script:
#!/bin/bash
# Start service
python3 your_service.py &
SERVICE_PID=$!
# Wait for service startup
sleep 5
# Run client tests
python3 your_client.py
# Cleanup
kill $SERVICE_PID
wait $SERVICE_PID 2>/dev/null- Test successful cases
- Test validation errors
- Test service errors
- Test timeouts
- Test resource cleanup
Issue: Client cannot discover service Solutions:
- Ensure service is running
- Check domain_id matches
- Increase discovery timeout
- Verify network connectivity
Issue: Function calls fail validation Solutions:
- Check input values match schemas
- Verify validation patterns match between client and service
- Enable debug logging to see validation details
Issue: Resources not properly released Solutions:
- Use try/finally blocks
- Call client.close() after use
- Handle KeyboardInterrupt
- Use context managers when possible
Issue: Service rejects client calls Solutions:
- Ensure schemas match exactly
- Copy schemas instead of reusing
- Check required vs optional parameters
- Verify parameter types
- Always validate inputs
- Use descriptive error messages
- Log all function calls
- Include original inputs in responses
- Clean up resources properly
- Use type hints
- Document all functions
- Validate before calling service
- Handle all error cases
- Use appropriate timeouts
- Clean up resources
- Log service calls
- Include comprehensive tests
- Use common schemas when possible
- Follow consistent naming patterns
- Document error conditions
- Test edge cases
- Handle interruptions gracefully
- Use async/await properly
- Keep functions focused and simple
See the template files for complete examples:
templates/service_template.pytemplates/client_template.py
(c) 2025 Copyright, Real-Time Innovations, Inc. (RTI) All rights reserved.
RTI grants Licensee a license to use, modify, compile, and create derivative works of the Software. Licensee has the right to distribute object form only for use with RTI products. The Software is provided "as is", with no warranty of any type, including any warranty for fitness for any purpose. RTI is under no obligation to maintain or support the Software. RTI shall not be liable for any incidental or consequential damages arising out of the use or inability to use the software.