rhailib/docs/TASK_LIFECYCLE_VERIFICATION.md

2.3 KiB

Task Lifecycle Verification

Test: Spawned Task Continues After Function Returns

use tokio::time::{sleep, Duration};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

#[tokio::test]
async fn test_spawned_task_continues() {
    let completed = Arc::new(AtomicBool::new(false));
    let completed_clone = completed.clone();
    
    // Function that spawns a task and returns immediately
    fn spawn_long_task(flag: Arc<AtomicBool>) -> String {
        tokio::spawn(async move {
            // Simulate HTTP request (2 seconds)
            sleep(Duration::from_secs(2)).await;
            
            // Mark as completed
            flag.store(true, Ordering::SeqCst);
            println!("Background task completed!");
        });
        
        // Return immediately
        "task_spawned".to_string()
    }
    
    // Call the function
    let result = spawn_long_task(completed_clone);
    assert_eq!(result, "task_spawned");
    
    // Function returned, but task should still be running
    assert_eq!(completed.load(Ordering::SeqCst), false);
    
    // Wait for background task to complete
    sleep(Duration::from_secs(3)).await;
    
    // Verify task completed successfully
    assert_eq!(completed.load(Ordering::SeqCst), true);
}

Test Results

Function returns immediately (microseconds) Spawned task continues running (2+ seconds)
Task completes successfully after function has returned No blocking or hanging

Real-World Behavior

// Rhai calls this function
let result = payment_intent.create_async("worker-1", "context-123", "sk_test_...");
// result = "payment_intent_request_dispatched" (returned in ~1ms)

// Meanwhile, in the background (2-5 seconds later):
// 1. HTTP request to Stripe API
// 2. Response received
// 3. New Rhai script dispatched: "flows/new_create_payment_intent_response.rhai"

Key Guarantees

  1. Non-blocking: Rhai function returns immediately
  2. Fire-and-forget: HTTP request continues in background
  3. Event-driven: Response triggers new script execution
  4. No memory leaks: Task is self-contained with moved ownership
  5. Runtime managed: tokio handles task scheduling and cleanup

The spawned task is completely independent and will run to completion regardless of what happens to the function that created it.