Rust RQD
High-performance Rust implementation of the OpenCue render host agent
Overview
The Rust RQD is a modern reimplementation of the OpenCue RQD (Render Queue Daemon) agent, written in Rust for improved performance, memory safety, and resource efficiency. Located in the rust/ folder of the OpenCue repository, this implementation maintains full compatibility with the OpenCue ecosystem while offering several advantages over the Python version.
What is Rust RQD?
Rust RQD serves the same core function as the traditional Python RQD - it’s the agent software that runs on render hosts to:
- Register hosts with Cuebot
- Receive and execute rendering tasks
- Monitor system resources and frame execution
- Report status and results back to Cuebot
Key Differences from Python RQD
The Rust implementation offers several advantages:
- Performance: Lower CPU and memory overhead, faster startup times
- Memory Safety: Rust’s ownership system prevents memory leaks and data races
- Concurrency: Built on Tokio async runtime for efficient concurrent operations
- Type Safety: Compile-time guarantees reduce runtime errors
- Resource Monitoring: More efficient system resource tracking with minimal overhead
- Container Support: Experimental support for running frames in Docker containers
When to Use Rust RQD
Consider using the Rust RQD when:
- You need improved performance on render hosts
- Running in resource-constrained environments
- Deploying at scale where efficiency matters
- Testing experimental features like containerized frames
- Contributing to the next generation of OpenCue infrastructure
Installation
Using Pre-built Binaries (Recommended)
The easiest way to get started with Rust RQD is to use the pre-built binaries from GitHub releases:
-
Download the appropriate binary for your platform from the OpenCue releases page:
- Linux (GNU):
openrqd-VERSION-x86_64-unknown-linux-gnu - Linux (MUSL):
openrqd-VERSION-x86_64-unknown-linux-musl(static binary, no dependencies) - macOS (Intel):
openrqd-VERSION-x86_64-apple-darwin - macOS (Apple Silicon):
openrqd-VERSION-aarch64-apple-darwin
- Linux (GNU):
- Make the binary executable:
chmod +x openrqd-VERSION-PLATFORM - Optionally, rename and move to your PATH:
mv openrqd-VERSION-PLATFORM /usr/local/bin/openrqd
Available Binary Platforms
The following pre-built binaries are available for each OpenCue release:
| Platform | Filename Pattern | Description |
|---|---|---|
| Linux (GNU) | openrqd-VERSION-x86_64-unknown-linux-gnu |
Standard Linux binary, requires glibc |
| Linux (MUSL) | openrqd-VERSION-x86_64-unknown-linux-musl |
Static binary with no runtime dependencies, ideal for containers |
| macOS (Intel) | openrqd-VERSION-x86_64-apple-darwin |
Intel-based Mac systems |
| macOS (Apple Silicon) | openrqd-VERSION-aarch64-apple-darwin |
M1/M2/M3 Mac systems |
Which Linux binary should I use?
- Use the GNU version for most Linux distributions (Ubuntu, Debian, RHEL, CentOS, etc.)
- Use the MUSL version for Alpine Linux, containers, or when you need a completely self-contained binary
Building from Source
If you need to customize the build or contribute to development, you can build from source:
Prerequisites
- Install Rust: Follow the official guide at rustup.rs
-
Install Protobuf Compiler:
macOS:
brew install protobufUbuntu/Debian:
sudo apt-get install protobuf-compilerRHEL/CentOS/Rocky:
sudo yum install protobuf-compiler
Build Instructions
- Navigate to the Rust directory:
cd OpenCue/rust - Build the project:
# Production build (recommended) cargo build --release # Debug build (includes both Linux and macOS versions) cargo buildNote: Release builds (
cargo build -r) compile the OS-specific version, while debug builds compile both Linux and macOS versions to enable cross-platform development. - The binary will be available at:
- Release:
target/release/openrqd - Debug:
target/debug/openrqd
- Release:
Build Features
The Rust RQD supports optional features through Cargo:
# Enable experimental containerized frames support
cargo build --release --features containerized_frames
Running Rust RQD
Quick Start with Pre-built Binary
-
Download and prepare the binary (as shown in the Installation section above)
- Create a basic configuration (optional - RQD can run with defaults):
mkdir -p ~/.config/openrqd # Copy sample config and modify as needed - Run RQD:
# If you placed it in your PATH openrqd # Or run directly ./openrqd-VERSION-PLATFORM
Local Development
- Start the dummy Cuebot server (for testing, requires building from source):
target/release/dummy-cuebot report-server -
Run RQD with configuration:
Using real configuration:
# With pre-built binary openrqd # With source build target/release/openrqdUsing fake Linux environment (for testing on macOS):
env OPENCUE_RQD_CONFIG=/path/to/OpenCue/rust/config/rqd.fake_linux.yaml openrqd - Launch a test frame (requires building dummy-cuebot from source):
target/release/dummy-cuebot rqd-client launch-frame \ /path/to/OpenCue/rust/crates/rqd/resources/test_scripts/memory_fork.sh
Production Deployment
- Install the binary: Download the appropriate pre-built binary for your platform and install it:
# Download from GitHub releases curl -L -o openrqd https://github.com/AcademySoftwareFoundation/OpenCue/releases/latest/download/openrqd-VERSION-PLATFORM chmod +x openrqd sudo mv openrqd /usr/local/bin/ - Configure RQD: Edit
/etc/openrqd/rqd.yamlor setOPENCUE_RQD_CONFIGenvironment variable - Set Cuebot hostname: Configure the Cuebot server location in your configuration file
-
Run as a service:
systemd (Linux):
sudo systemctl enable openrqd sudo systemctl start openrqd
Docker Support (Experimental)
The Rust RQD includes experimental support for running frames in Docker containers:
- Build with container support:
cargo build --release --features containerized_frames - Configure Docker settings in
rqd.yaml - Ensure Docker daemon is running and accessible
Configuration
The Rust RQD uses YAML configuration files with extensive customization options:
- Default location:
/etc/openrqd/rqd.yaml - Override with environment:
OPENCUE_RQD_CONFIG=/path/to/config.yaml - Sample configs: Available in
rust/config/directory
Key configuration sections:
- System resource limits (CPU, memory)
- Network settings and Cuebot connection
- Logging configuration
- NIMBY (Not In My Back Yard) settings
- Container runtime settings (when enabled)
- Log-based exit-status rules (see below)
Log-Based Exit-Status Rules
When a frame exits with a non-zero code, RQD can reclassify the failure by scanning the tail of the frame log against operator-defined regular expressions. On the first matching rule, RQD reports that rule’s exit_status to Cuebot instead of the process’s real exit code. This lets operators single out failures that deserve special dispatcher handling — for example a Houdini license shortage that exits 3 but should be retried differently — without the render wrapper having to translate the error into an exit code itself.
Configure it in the runner section of rqd.yaml:
runner:
# Number of trailing log lines scanned on failure (default: 50).
# Set to 0, or leave log_exit_status_rules empty, to disable scanning.
log_scan_last_lines: 50
# Ordered regex -> exit-status rules. Evaluated top-to-bottom; first match wins.
log_exit_status_rules:
- name: "HOUDINI_LICENSE_ERROR"
regex: "A usable license to run the application is installed but they are all in use"
exit_status: 330
Behavior notes:
- Disabled by default: the feature does nothing until
log_exit_status_rulesis non-empty andlog_scan_last_linesis greater than0. - Failures only: successful frames (exit
0) are never scanned, so there is no overhead on the happy path. - First match wins: place more specific patterns above general ones.
name: a human-readable identifier used only in RQD’s log messages to make matches easy to trace.- Invalid regex is skipped (with a warning) rather than disabling the whole rule set.
- Efficient tail read: the log tail is read backward in fixed-size chunks and stops once enough lines are collected — typically only a few kilobytes are read even for large logs, with a hard 1 MiB cap so a pathologically large log is never read in full.
Cuebot-side handling: automatic layer backoff
A substitute exit status is most useful when Cuebot is told what to do with it. Cuebot’s
dispatcher.layer_delay.rules property (in opencue.properties) maps exit statuses to a number of
minutes; when a frame reports a configured status, Cuebot defers booking of the frame’s whole layer
for that long (layer.ts_start_after) instead of consuming a retry or killing the frame — the
right behavior for a shared-resource shortage like a license pool, where every frame of the layer
would hit the same wall:
# Comma-separated exit_status:minutes pairs. Empty (default) disables the feature.
# Must agree with the exit statuses configured in rqd.yaml log_exit_status_rules.
dispatcher.layer_delay.rules=330:5
The exit status is an arbitrary number chosen in rqd.yaml and repeated in opencue.properties;
330 is the conventional license-shortage code. Delayed layers are visible in CueGUI (tinted row
plus a Start After column) and in the cuebot_layers_delayed / cuebot_layer_delays_total
Prometheus metrics.
Testing
Unit Tests
Run the test suite:
cd OpenCue/rust
cargo test
Integration Tests
The Rust RQD includes comprehensive integration tests:
cargo test --test rqd_integration_tests
Monitoring Logs
- Frame logs: Located at
/tmp/rqd/test_job.test_frame.rqlog - RQD logs: Configured via
rqd.yamlor console output
Contributing
Development Workflow
- Code Quality:
# Format code cargo fmt # Run linter cargo clippy -- -D warnings # Check for common mistakes cargo check - Testing:
# Run all tests cargo test # Run with coverage (requires cargo-tarpaulin) cargo tarpaulin - Documentation:
# Generate and view docs cargo doc --open
Project Structure
rust/
├── crates/
│ ├── rqd/ # Main RQD implementation
│ │ ├── src/
│ │ │ ├── config/ # Configuration management
│ │ │ ├── frame/ # Frame execution and management
│ │ │ ├── report/ # Reporting to Cuebot
│ │ │ ├── servant/ # gRPC service implementations
│ │ │ └── system/ # System monitoring (CPU, memory, etc.)
│ │ └── tests/ # Integration tests
│ ├── opencue-proto/ # Protocol buffer definitions
│ └── dummy-cuebot/ # Test server implementation
└── config/ # Sample configuration files
Code Style Guidelines
- Follow Rust standard conventions
- Use
cargo fmtbefore committing - Address all
cargo clippywarnings - Write tests for new functionality
- Document public APIs with rustdoc comments
Key Features
Core Functionality
- Full Cuebot compatibility: Works with existing OpenCue infrastructure
- Multi-platform support: Linux, MacOS and Windows
- Efficient resource monitoring: Low-overhead CPU, memory, and disk tracking
- Process management: Reliable frame execution and monitoring
- Automatic recovery: Resilient error handling and retry mechanisms
Advanced Features
- Async architecture: Built on Tokio for high-performance I/O
- Configurable logging: Structured logging with multiple output formats
- NIMBY support: Automatic idle detection and resource management
- Signal handling: Graceful shutdown and frame cleanup
- Reservation system: Resource allocation and management
- Log-based exit-status rules: Reclassify failed frames by matching their log output against configurable regex rules (e.g. flag license shortages)
Experimental Features
- Containerized frames: Run frames in isolated Docker containers
- Enhanced security: Improved process isolation and resource limits
Current Limitations
While the Rust RQD is production-ready for many use cases, be aware of:
- Container support: Experimental feature, not recommended for production
- Plugin system: Python RQD plugins not yet supported
- Custom resource handlers: Limited compared to Python version
- GPU monitoring: Basic support, full feature parity in progress
Performance Comparison
Typical improvements over Python RQD:
- Memory usage: 50-70% reduction
- CPU overhead: 30-40% lower
- Startup time: 5-10x faster
- Frame launch latency: 20-30% improvement
- Concurrent frame handling: 2-3x better throughput
Troubleshooting
Common Issues
- Build failures: Ensure protobuf compiler is installed
- Connection errors: Verify Cuebot hostname and network connectivity
- Permission denied: Check file permissions and user privileges
- Resource detection: Verify system monitoring works with
sysinfocrate
Debug Mode
Enable verbose logging:
RUST_LOG=debug target/release/openrqd
Getting Help
- Check logs in
/var/log/openrqd/or configured location - Review configuration with
openrqd --validate-config - File issues at OpenCue GitHub
Migration from Python RQD
Compatibility
The Rust RQD maintains full protocol compatibility with Cuebot, allowing:
- Drop-in replacement in existing deployments
- Mixed environments (some Python, some Rust RQDs)
- Gradual migration strategies
Migration Steps
- Test in isolation: Deploy to test hosts first
- Compare behavior: Monitor logs and performance metrics
- Gradual rollout: Deploy to production hosts incrementally
- Monitor metrics: Track resource usage and frame success rates
Configuration Migration
Most Python RQD configurations map directly:
- Network settings remain the same
- Resource limits use same units
- Log formats are compatible
- File paths follow same conventions
Future Roadmap
Planned enhancements include:
- Enhanced GPU resource management
- Plugin system for custom extensions
- Improved container orchestration
- Performance profiling tools
- Extended telemetry and metrics