use ops_rs::prelude::*;
use ops_rs::{break_loop, repeat_until};
#[derive(Debug)]
struct LoadContentOp {
prefix: String,
}
impl LoadContentOp {
fn new(prefix: String) -> Self {
Self { prefix }
}
}
#[async_trait]
impl Op<()> for LoadContentOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<()> {
let iteration = dry.get::<usize>(&self.prefix).unwrap_or(0);
println!(" Loading content for iteration {}", iteration);
dry.insert("content_length", iteration * 1000);
Ok(())
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("LoadContentOp").build()
}
}
#[derive(Debug)]
struct InsertDataOp {
config: String,
}
impl InsertDataOp {
fn with(config: impl Into<String>) -> Self {
Self {
config: config.into(),
}
}
}
#[async_trait]
impl Op<()> for InsertDataOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<()> {
println!(" Inserting data with config: {}", self.config);
let iteration = dry.get::<usize>("cso").unwrap_or(0);
let content_quality = match iteration {
0..=1 => "insufficient", 2 => "adequate", _ => "excellent", };
dry.insert("content_quality", content_quality.to_string());
println!(" AI Analysis: Content quality is {}", content_quality);
Ok(())
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("InsertDataOp").build()
}
}
#[derive(Debug)]
struct MakeDecisionOp;
#[async_trait]
impl Op<()> for MakeDecisionOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<()> {
let content_quality = dry
.get::<String>("content_quality")
.unwrap_or_else(|| "unknown".to_string());
println!(" MakeDecision processing quality: {}", content_quality);
Ok(())
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("MakeDecisionOp").build()
}
}
#[derive(Debug)]
struct ReactToContentSelectionResponse;
#[async_trait]
impl Op<()> for ReactToContentSelectionResponse {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<()> {
let content_quality = dry
.get::<String>("content_quality")
.unwrap_or_else(|| "unknown".to_string());
let iteration = dry.get::<usize>("cso").unwrap_or(0);
println!(" Reacting to content selection: {}", content_quality);
match content_quality.as_str() {
"insufficient" => {
if iteration >= 4 {
println!(" ERR Too many failed attempts, giving up");
break_loop!(dry); } else {
println!(" Content insufficient, will try again");
dry.insert("should_continue", true);
}
}
"adequate" => {
println!(" OK Content is adequate, we can proceed");
dry.insert("selection_result", "adequate");
break_loop!(dry); }
"excellent" => {
println!(" Excellent content found!");
dry.insert("selection_result", "excellent");
break_loop!(dry); }
_ => {
println!(" WARN Unknown quality, continuing...");
dry.insert("should_continue", true);
}
}
Ok(())
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("ReactToContentSelectionResponse").build()
}
}
repeat_until! {
ContentSelectionOp<()> -> unit = {
counter: "cso",
condition: "should_continue",
max_iterations: 10,
ops: [
LoadContentOp::new("cso".to_string()),
InsertDataOp::with("ai_analysis_config"),
MakeDecisionOp,
ReactToContentSelectionResponse
]
}
}
#[derive(Debug)]
struct StartTransactionOp;
#[async_trait]
impl Op<()> for StartTransactionOp {
async fn perform(&self, _dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<()> {
println!(" Starting transaction");
Ok(())
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("StartTransactionOp").build()
}
}
repeat_until! {
CloseReadOpBatch<()> -> unit = {
counter: "extraction_step",
condition: "extraction_active",
max_iterations: 5,
ops: [
StartTransactionOp,
ContentSelectionOp::new()
]
}
}
#[tokio::main]
async fn main() -> OpResult<()> {
let mut dry = DryContext::new();
let mut wet = WetContext::new();
println!(" CONTENT SELECTION WITH INTELLIGENT BREAK/CONTINUE \n");
println!("=== Test 1: Finding adequate content ===");
dry.insert("should_continue", true);
let content_op = ContentSelectionOp::new();
match content_op.perform(&mut dry, &mut wet).await {
Ok(_) => {
let result = dry.get::<String>("selection_result");
println!("OK Content selection completed with result: {:?}", result);
}
Err(e) => println!("ERR Error: {}", e),
}
println!("\n=== Test 2: Full extraction pipeline ===");
dry.clear_control_flags();
dry.insert("should_continue", true);
dry.insert("extraction_active", true);
let extraction_pipeline = CloseReadOpBatch::new();
match extraction_pipeline.perform(&mut dry, &mut wet).await {
Ok(_) => {
let result = dry.get::<String>("selection_result");
println!("OK Extraction pipeline completed with result: {:?}", result);
}
Err(e) => println!("ERR Error: {}", e),
}
println!("\n SUMMARY:");
println!("• Your ContentSelectionOp now intelligently uses break_loop! to stop when:");
println!(" - Content quality is 'adequate' or 'excellent'");
println!(" - Too many failed attempts (>4)");
println!("• continue_loop! could be used to skip iterations if needed");
println!("• The condition variable 'should_continue' controls the loop");
println!("• max_iterations provides a safety limit");
Ok(())
}