Skip to main content

internal_lessons_lifecycle/
lessons_lifecycle.rs

1#[path = "../support/utils.rs"]
2mod _utils;
3
4use _utils::{boxed_error, cleanup_run, create_client, new_run_id, print_summary, require};
5use mubit_sdk::{RememberOptions, TransportMode};
6use serde_json::{json, Value};
7use std::error::Error;
8use std::time::Instant;
9use tokio::time::{sleep, Duration};
10
11#[tokio::main(flavor = "current_thread")]
12async fn main() -> Result<(), Box<dyn Error>> {
13    let name = "internal_lessons_lifecycle";
14    let started = Instant::now();
15    let client = create_client().await?;
16    let run_id = new_run_id("internal_lessons_lifecycle");
17    client.set_run_id(Some(run_id.clone()));
18    client.set_transport(TransportMode::Http);
19    let mut passed = true;
20    let mut detail = "validated raw lessons lifecycle".to_string();
21    let mut metrics = json!({});
22
23    let scenario = async {
24        let mut remember = RememberOptions::new("Always verify the stored deductible before approving reimbursement.");
25        remember.run_id = Some(run_id.clone());
26        remember.intent = Some("lesson".into());
27        remember.lesson_type = Some("success".into());
28        remember.lesson_scope = Some("session".into());
29        client.remember(remember).await?;
30
31        let mut lessons = serde_json::Value::Null;
32        for _ in 0..24 {
33            let current = client
34                .control
35                .lessons(json!({"run_id": run_id, "limit": 10}))
36                .await?;
37            let has_lesson = current
38                .get("lessons")
39                .and_then(|v| v.as_array())
40                .map(|items| !items.is_empty())
41                .unwrap_or(false);
42            lessons = current;
43            if has_lesson {
44                break;
45            }
46            sleep(Duration::from_millis(500)).await;
47        }
48        let lesson_id = lessons.get("lessons").and_then(|v| v.as_array()).and_then(|items| items.iter().find_map(|item| item.get("id").and_then(|v| v.as_str()))).ok_or_else(|| boxed_error(format!("expected lesson in lifecycle test: {lessons}")))?.to_string();
49        let deleted = client.control.delete_lesson(json!({"lesson_id": lesson_id})).await?;
50        let remaining = client.control.lessons(json!({"run_id": run_id, "limit": 10})).await?;
51        require(deleted.get("success").and_then(Value::as_bool).unwrap_or(true), format!("delete_lesson failed: {deleted}"))?;
52        require(!remaining.get("lessons").and_then(|v| v.as_array()).map(|items| items.iter().any(|item| item.get("id").and_then(|v| v.as_str()) == Some(lesson_id.as_str()))).unwrap_or(false), format!("lesson still present after delete: {remaining}"))?;
53        metrics = json!({"run_id": run_id, "lesson_id": lesson_id});
54        Ok::<(), Box<dyn Error>>(())
55    }.await;
56
57    if let Err(err) = scenario { passed = false; detail = err.to_string(); }
58    let cleanup_ok = cleanup_run(&client, &run_id).await;
59    if !cleanup_ok { passed = false; detail = format!("{detail} | cleanup failures"); }
60    print_summary(name, passed, &detail, &metrics, started.elapsed().as_secs_f64(), cleanup_ok);
61    if passed { Ok(()) } else { Err(boxed_error(detail)) }
62}