Integration Guide¶
This guide demonstrates how to integrate AirsSys components effectively.
Overview¶
AirsSys components can be used independently or combined for powerful system programming solutions:
- OSL alone: Secure OS operations
- RT alone: Actor-based concurrency
- OSL + RT: Supervised secure operations
Pattern 1: OSL Operations in RT Actors¶
Wrap OSL helper functions in RT actors:
use airssys_rt::prelude::*;
use airssys_osl::helpers::*;
use async_trait::async_trait;
#[derive(Debug, Clone)]
enum FileServiceMsg {
ReadFile(String, tokio::sync::oneshot::Sender<Vec<u8>>),
WriteFile(String, Vec<u8>),
}
impl Message for FileServiceMsg {
const MESSAGE_TYPE: &'static str = "file-service";
}
struct FileServiceActor {
principal: String,
}
#[async_trait]
impl Actor for FileServiceActor {
type Message = FileServiceMsg;
type Error = Box<dyn std::error::Error + Send + Sync>;
async fn handle_message<B: MessageBroker<Self::Message>>(
&mut self,
msg: Self::Message,
_ctx: &mut ActorContext<Self::Message, B>,
) -> Result<(), Self::Error> {
match msg {
FileServiceMsg::ReadFile(path, reply) => {
// Use OSL with security
let content = read_file(&path, &self.principal).await?;
let _ = reply.send(content);
}
FileServiceMsg::WriteFile(path, data) => {
write_file(&path, data, &self.principal).await?;
}
}
Ok(())
}
}
Benefits: - OSL security policies automatically enforced - RT fault tolerance for file operations - Actor isolation prevents shared state issues
Pattern 2: Using OSLSupervisor¶
The built-in OSLSupervisor manages filesystem, process, and network actors:
use airssys_rt::supervisor::OSLSupervisor;
use airssys_rt::broker::InMemoryMessageBroker;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create shared broker
let broker = InMemoryMessageBroker::new();
// Create OSL supervisor
let supervisor = OSLSupervisor::new(broker.clone());
// Start all OSL actors with supervision
supervisor.start().await?;
// Actors are now running:
// - FileSystemActor at "osl-filesystem"
// - ProcessActor at "osl-process"
// - NetworkActor at "osl-network"
// They automatically restart on failure (RestForOne strategy)
println!("OSL system running with supervision");
// Keep running
tokio::signal::ctrl_c().await?;
Ok(())
}
Architecture:
Pattern 3: Custom Security in RT Actors¶
Use OSL middleware directly in RT actors:
use airssys_rt::prelude::*;
use airssys_osl::middleware::security::*;
struct SecureActor {
security: SecurityMiddleware,
}
#[async_trait]
impl Actor for SecureActor {
type Message = SecureMsg;
type Error = Box<dyn std::error::Error + Send + Sync>;
async fn handle_message<B: MessageBroker<Self::Message>>(
&mut self,
msg: Self::Message,
_ctx: &mut ActorContext<Self::Message, B>,
) -> Result<(), Self::Error> {
// Check security before processing
self.security.check_access(&msg.resource, &msg.principal)?;
// Process message
// ...
Ok(())
}
}
Pattern 4: Hierarchical Supervision with OSL¶
Build supervision trees with OSL operations at leaves:
use airssys_rt::supervisor::*;
// Root supervisor
let root = SupervisorBuilder::new()
.with_strategy(RestartStrategy::OneForOne)
.build();
// Add OSL supervisor as child
let osl_supervisor = OSLSupervisor::new(broker.clone());
root.add_child("osl", Box::new(osl_supervisor), RestartPolicy::Permanent).await?;
// Add application supervisor as child
let app_supervisor = AppSupervisor::new(broker.clone());
root.add_child("app", Box::new(app_supervisor), RestartPolicy::Permanent).await?;
// Start entire tree
root.start().await?;
Architecture:
RootSupervisor
├─→ OSLSupervisor
│ ├─→ FileSystemActor
│ ├─→ ProcessActor
│ └─→ NetworkActor
└─→ AppSupervisor
├─→ BusinessActor1
└─→ BusinessActor2
Pattern 5: Message-Based OS Operations¶
Define operation messages for OSL actors:
#[derive(Debug, Clone)]
enum OSLMessage {
FileRead { path: String, reply: Sender<Vec<u8>> },
FileWrite { path: String, data: Vec<u8> },
ProcessSpawn { cmd: String, args: Vec<String> },
}
impl Message for OSLMessage {
const MESSAGE_TYPE: &'static str = "osl";
}
// Send message to OSL actor
broker.publish(
OSLMessage::FileRead {
path: "/tmp/test.txt".to_string(),
reply: tx,
},
ActorAddress::new("osl-filesystem"),
).await?;
Integration Checklist¶
For OSL + RT Integration¶
- Create shared message broker
- Define message types for OS operations
- Create OSL actors or use OSLSupervisor
- Configure security policies
- Set up supervision strategies
- Add monitoring/logging
- Test failure recovery
Security Considerations¶
- OSL security policies configured
- Principals assigned to actors
- Audit logging enabled
- Actor isolation verified
- No shared mutable state
Performance Considerations¶
- Mailbox sizes tuned
- Backpressure strategy chosen
- Message batching where appropriate
- Monitoring metrics collected
Common Patterns¶
Request-Reply with OSL¶
// Actor receives request
async fn handle_message(&mut self, msg: Msg) {
match msg {
Msg::GetFile(path, reply) => {
// Use OSL
let content = read_file(&path, &self.principal).await?;
// Send reply
let _ = reply.send(content);
}
}
}
Fire-and-Forget with OSL¶
async fn handle_message(&mut self, msg: Msg) {
match msg {
Msg::LogEvent(event) => {
// Use OSL asynchronously
write_file(&log_path, event.as_bytes(), "logger").await?;
// No reply needed
}
}
}
Streaming with OSL¶
async fn handle_message(&mut self, msg: Msg) {
match msg {
Msg::StreamFile(path) => {
// Read in chunks
let mut offset = 0;
loop {
let chunk = read_file_chunk(&path, offset, 4096).await?;
if chunk.is_empty() {
break;
}
// Process chunk
offset += chunk.len();
}
}
}
}
Testing Integration¶
Unit Testing¶
Test actors independently:
#[tokio::test]
async fn test_file_service_actor() {
let broker = InMemoryMessageBroker::new();
let actor = FileServiceActor::new("test-user");
// Test actor behavior
}
Integration Testing¶
Test complete system:
#[tokio::test]
async fn test_osl_supervision() {
let broker = InMemoryMessageBroker::new();
let supervisor = OSLSupervisor::new(broker.clone());
supervisor.start().await.unwrap();
// Test operations work
// Test failure recovery
}
Best Practices¶
- Use OSLSupervisor for standard OS operations
- Define clear message types for operations
- Configure security policies before starting actors
- Enable monitoring for production systems
- Test failure scenarios to verify recovery
- Document supervision trees for maintenance