* fix(tasks): avoid dropping completed task results during collection * chore(tasks): make `task_result_receiver` required * refactor(tasks): make `collect_completed_results` private
77 lines
2.1 KiB
Rust
77 lines
2.1 KiB
Rust
use std::{any::Any, time::Duration};
|
|
|
|
use rmcp::task_manager::{
|
|
OperationDescriptor, OperationMessage, OperationProcessor, OperationResultTransport,
|
|
};
|
|
|
|
struct DummyTransport {
|
|
id: String,
|
|
value: u32,
|
|
}
|
|
|
|
impl OperationResultTransport for DummyTransport {
|
|
fn operation_id(&self) -> &String {
|
|
&self.id
|
|
}
|
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
self
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn executes_enqueued_future() {
|
|
let mut processor = OperationProcessor::new();
|
|
let descriptor = OperationDescriptor::new("op1", "dummy");
|
|
let future = Box::pin(async {
|
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
|
Ok(Box::new(DummyTransport {
|
|
id: "op1".to_string(),
|
|
value: 42,
|
|
}) as Box<dyn OperationResultTransport>)
|
|
});
|
|
|
|
processor
|
|
.submit_operation(OperationMessage::new(descriptor, future))
|
|
.expect("submit operation");
|
|
|
|
tokio::time::sleep(Duration::from_millis(30)).await;
|
|
let results = processor.peek_completed();
|
|
assert_eq!(results.len(), 1);
|
|
let payload = results[0]
|
|
.result
|
|
.as_ref()
|
|
.unwrap()
|
|
.as_any()
|
|
.downcast_ref::<DummyTransport>()
|
|
.unwrap();
|
|
assert_eq!(payload.value, 42);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn rejects_duplicate_operation_ids() {
|
|
let mut processor = OperationProcessor::new();
|
|
let descriptor = OperationDescriptor::new("dup", "dummy");
|
|
let future = Box::pin(async {
|
|
Ok(Box::new(DummyTransport {
|
|
id: "dup".to_string(),
|
|
value: 1,
|
|
}) as Box<dyn OperationResultTransport>)
|
|
});
|
|
processor
|
|
.submit_operation(OperationMessage::new(descriptor, future))
|
|
.expect("first submit");
|
|
|
|
let descriptor_dup = OperationDescriptor::new("dup", "dummy");
|
|
let future_dup = Box::pin(async {
|
|
Ok(Box::new(DummyTransport {
|
|
id: "dup".to_string(),
|
|
value: 2,
|
|
}) as Box<dyn OperationResultTransport>)
|
|
});
|
|
|
|
let err = processor
|
|
.submit_operation(OperationMessage::new(descriptor_dup, future_dup))
|
|
.expect_err("duplicate should fail");
|
|
assert!(format!("{err}").contains("already running"));
|
|
}
|