IPC (Inter-Process Communication)¶
The IPC module enables communication with remote RayforceDB instances.
Overview¶
IPC allows you to:
- Connect to remote RayforceDB servers
- Execute queries remotely
- Transfer data between processes
- Build distributed systems
Connection¶
Opening a Connection¶
use rayforce::ipc::{Connection, hopen};
// Connect to remote server
let conn = hopen("localhost", 5000)?;
// With timeout (milliseconds)
let conn = hopen_timeout("localhost", 5000, 5000)?;
Connection Management¶
// Check if connected
if conn.is_connected() {
println!("Connected!");
}
// Close connection
conn.close()?;
Executing Queries¶
Send and Receive¶
use rayforce::ipc::Connection;
let conn = hopen("localhost", 5000)?;
// Execute query
let result = conn.execute("(+ 1 2 3)")?;
println!("Result: {}", result);
// Execute with parameters
let result = conn.execute("(select { from: trades })")?;
Async Execution¶
Data Transfer¶
Sending Data¶
use rayforce::{RayObj, RayVector};
use rayforce::ipc::Connection;
let conn = hopen("localhost", 5000)?;
// Send vector
let prices: RayVector<i64> = RayVector::from_iter([100, 200, 300]);
conn.write(&prices)?;
// Send with assignment
conn.execute("(set remote_prices prices)")?;
Receiving Data¶
// Execute and receive result
let table = conn.execute("trades")?;
println!("Received: {}", table);
// Receive specific columns
let prices = conn.execute("(. trades 'price)")?;
Connection Pool¶
For high-throughput applications:
use rayforce::ipc::ConnectionPool;
// Create connection pool
let pool = ConnectionPool::new("localhost", 5000, 10)?;
// Get connection from pool
let conn = pool.get()?;
// Use connection
let result = conn.execute("(+ 1 2)")?;
// Connection returns to pool when dropped
Error Handling¶
Connection Errors¶
use rayforce::ipc::{hopen, IPCError};
match hopen("localhost", 5000) {
Ok(conn) => println!("Connected!"),
Err(IPCError::ConnectionFailed(msg)) => {
eprintln!("Connection failed: {}", msg);
}
Err(IPCError::Timeout) => {
eprintln!("Connection timed out");
}
Err(e) => eprintln!("Error: {}", e),
}
Query Errors¶
match conn.execute("(invalid_query") {
Ok(result) => println!("{}", result),
Err(e) => eprintln!("Query failed: {}", e),
}
Complete Example¶
use rayforce::{Rayforce, RayVector};
use rayforce::ipc::hopen;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to remote RayforceDB
let conn = hopen("localhost", 5000)?;
println!("Connected to RayforceDB server");
// Check server version
let version = conn.execute("(version)")?;
println!("Server version: {}", version);
// Create table on server
conn.execute(r#"
(set trades (table [sym price qty time]
(list
['AAPL 'MSFT 'AAPL]
[150.0 300.0 151.0]
[100 50 200]
[09:30:00 09:31:00 09:32:00])))
"#)?;
// Query data
let result = conn.execute(r#"
(select {
sym: sym
total_value: (sum (* price qty))
from: trades
by: sym})
"#)?;
println!("Trade summary:\n{}", result);
// Close connection
conn.close()?;
Ok(())
}
Server Setup¶
To run a RayforceDB server:
Or programmatically:
use rayforce::Rayforce;
let ray = Rayforce::new()?;
// Start listening (blocking)
ray.eval("(listen 5000)")?;
Protocol¶
RayforceDB IPC uses a binary protocol:
- Message header: Type + length
- Payload: Serialized RayforceDB objects
- Response: Result or error
Security Considerations¶
Network Security
RayforceDB IPC does not include built-in encryption. Use SSH tunnels or VPNs for secure connections over untrusted networks.
SSH Tunnel¶
# Create SSH tunnel
ssh -L 5000:localhost:5000 user@remote-server
# Connect via tunnel
let conn = hopen("localhost", 5000)?;
Firewall Rules¶
# Allow only local connections
iptables -A INPUT -p tcp --dport 5000 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 5000 -j DROP
Performance Tips¶
Keep Connections Open¶
Reuse connections instead of reconnecting:
// Good: reuse connection
let conn = hopen("localhost", 5000)?;
for query in queries {
conn.execute(&query)?;
}
// Bad: reconnect each time
for query in queries {
let conn = hopen("localhost", 5000)?; // Overhead
conn.execute(&query)?;
}
Batch Queries¶
Combine multiple queries when possible:
// Good: single round-trip
let result = conn.execute(r#"
(list
(select { from: table1 })
(select { from: table2 })
(select { from: table3 }))
"#)?;
// Bad: multiple round-trips
let r1 = conn.execute("(select { from: table1 })")?;
let r2 = conn.execute("(select { from: table2 })")?;
let r3 = conn.execute("(select { from: table3 })")?;
Compress Large Data¶
For large transfers:
Next Steps¶
- FFI - Low-level bindings
- API Overview - Full API reference
- Examples - More code examples