# V Lang Actor Interface This module provides a V lang port of the Rust actor trait interface for the Hero Baobab system. It enables implementing actors in V lang with a simple interface: implement `process_job` and use `spawn` to run the actor. ## Architecture The V lang actor interface mirrors the Rust implementation with these key components: ```text ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ SyncActor │ │ AsyncActor │ │ MyCustomActor │ │ │ │ │ │ │ │ process_job() │ │ process_job() │ │ process_job() │ │ (sequential) │ │ (concurrent) │ │ (custom logic) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └───────────────┬───────────────────────────────┘ │ ┌───────▼───────┐ │ Actor Interface│ │ │ │ spawn_actor() │ │ process_job() │ │ config │ └───────────────┘ ``` ## Core Components ### Actor Interface All actors must implement the `Actor` interface: ```v pub interface Actor { // Process a single job - must be implemented by concrete actors process_job(job Job, mut redis_conn redisclient.Redis) ! // Get the actor type identifier actor_type() string // Get the actor ID actor_id() string // Get the Redis URL redis_url() string // Get the database path db_path() string // Check if tasks should be preserved preserve_tasks() bool } ``` ### ActorConfig Configuration structure for all actors: ```v pub struct ActorConfig { pub: actor_id string db_path string redis_url string preserve_tasks bool default_timeout ?time.Duration // Optional timeout for async actors } ``` ### Job Structure Jobs processed by actors: ```v pub struct Job { pub mut: id string caller_id string context_id string script string status JobStatus result string error string created_at time.Time started_at time.Time finished_at time.Time } ``` ## Built-in Actor Implementations ### SyncActor Processes jobs sequentially, one at a time: ```v import freeflowuniverse.herolib.lib.baobab.actor // Create configuration config := actor.new_actor_config( 'sync_actor_1', '/path/to/database', 'redis://localhost:6379', false ) // Create and spawn sync actor sync_actor := actor.new_sync_actor(config)! mut shutdown_chan := chan bool{cap: 1} go actor.spawn_actor(sync_actor, mut shutdown_chan) // Later, shutdown the actor shutdown_chan <- true ``` ### AsyncActor Processes jobs concurrently with timeout support: ```v import time import freeflowuniverse.herolib.lib.baobab.actor // Create configuration with timeout mut config := actor.new_actor_config( 'async_actor_1', '/path/to/database', 'redis://localhost:6379', false ) config = config.with_default_timeout(time.Duration(300 * time.second)) // Create and spawn async actor async_actor := actor.new_async_actor(config)! mut shutdown_chan := chan bool{cap: 1} go actor.spawn_actor(async_actor, mut shutdown_chan) // Later, shutdown the actor shutdown_chan <- true ``` ## Creating Custom Actors To implement a custom actor, simply implement the `Actor` interface: ```v import freeflowuniverse.herolib.lib.baobab.actor struct MyCustomActor { pub: config actor.ActorConfig mut: engine rhai.Engine // Add your custom fields here } pub fn new_custom_actor(config actor.ActorConfig) !MyCustomActor { mut engine := rhai.new_engine()! return MyCustomActor{ config: config engine: engine } } // Implement the Actor interface pub fn (mut actor MyCustomActor) process_job(job actor.Job, mut redis_conn redisclient.Redis) ! { // Your custom job processing logic here // Update job status to started actor.update_job_status(mut redis_conn, job.id, .started)! // Execute the script (or your custom logic) result := actor.execute_job_with_engine(mut actor.engine, job, actor.config.db_path)! // Update job status to finished and set result actor.update_job_status(mut redis_conn, job.id, .finished)! actor.set_job_result(mut redis_conn, job.id, result)! // Clean up if needed actor.cleanup_job(mut redis_conn, job.id, job.context_id, actor.config.preserve_tasks)! } // Implement required interface methods pub fn (actor MyCustomActor) actor_type() string { return 'MyCustomActor' } pub fn (actor MyCustomActor) actor_id() string { return actor.config.actor_id } pub fn (actor MyCustomActor) redis_url() string { return actor.config.redis_url } pub fn (actor MyCustomActor) db_path() string { return actor.config.db_path } pub fn (actor MyCustomActor) preserve_tasks() bool { return actor.config.preserve_tasks } // Usage config := actor.new_actor_config('my_actor', '/db/path', 'redis://localhost:6379', false) custom_actor := new_custom_actor(config)! mut shutdown_chan := chan bool{cap: 1} go actor.spawn_actor(custom_actor, mut shutdown_chan) ``` ## Key Features ### Unified Interface - Same `spawn_actor()` function works with all actor implementations - Consistent configuration and lifecycle management - Clean separation between actor logic and infrastructure ### Redis Integration - Automatic Redis connection management - Job polling from actor-specific queues (`hero:job:actor_queue:{actor_id}`) - Job status tracking and result storage - Optional job cleanup based on `preserve_tasks` setting ### Script Execution - Rhai script engine integration - Automatic job context setup (DB_PATH, CALLER_ID, CONTEXT_ID) - Error handling and status updates ### Graceful Shutdown - Channel-based shutdown signaling - Proper cleanup of resources - Support for cancelling running jobs (AsyncActor) ## Job Processing Flow 1. **Job Polling**: Actor polls Redis queue using BLPOP 2. **Job Loading**: Load job details from Redis hash 3. **Status Update**: Mark job as "started" 4. **Script Execution**: Execute Rhai script with job context 5. **Result Storage**: Store result or error in Redis 6. **Status Update**: Mark job as "finished" or "error" 7. **Cleanup**: Optionally remove job from Redis ## Error Handling All operations include comprehensive error handling: - Redis connection failures - Job loading errors - Script execution errors - Timeout handling (AsyncActor) - Graceful degradation and logging ## Migration from Rust This V lang implementation provides the same functionality as the Rust version: - ✅ Actor trait abstraction - ✅ Sync and async actor implementations - ✅ Unified spawn interface - ✅ Redis job queue integration - ✅ Rhai script execution - ✅ Job lifecycle management - ✅ Error handling and logging - ✅ Graceful shutdown ## Dependencies The actor interface depends on these herolib modules: - `freeflowuniverse.herolib.clients.redisclient` - Redis operations - `freeflowuniverse.herolib.data.rhai` - Script execution - `freeflowuniverse.herolib.core.base` - Base utilities ## Usage Summary To implement an actor in V lang: 1. **Create ActorConfig**: Configure actor ID, database path, Redis URL, etc. 2. **Implement Actor Interface**: Create a struct that implements the `Actor` interface 3. **Implement process_job()**: Add your job processing logic 4. **Use spawn()**: Call `spawn_actor()` to start the actor loop That's it! The interface handles all the Redis polling, job management, and infrastructure concerns automatically.