1use std::{collections::BTreeMap, sync::Arc};
2
3use async_trait::async_trait;
4
5use crate::{
6 contracts::{ExecutionRoute, HarnessKind, HarnessOutcome, HarnessRequest},
7 errors::HarnessError,
8};
9
10#[async_trait]
11pub trait HarnessAdapter: Send + Sync {
12 fn name(&self) -> &str;
13 fn kind(&self) -> HarnessKind;
14 async fn execute(&self, request: HarnessRequest) -> Result<HarnessOutcome, HarnessError>;
15}
16
17#[derive(Default)]
18pub struct HarnessBroker {
19 adapters: BTreeMap<String, Arc<dyn HarnessAdapter>>,
20}
21
22impl HarnessBroker {
23 #[must_use]
24 pub fn new() -> Self {
25 Self {
26 adapters: BTreeMap::new(),
27 }
28 }
29
30 pub fn register<A: HarnessAdapter + 'static>(&mut self, adapter: A) {
31 let key = adapter.name().to_owned();
32 self.adapters.insert(key, Arc::new(adapter));
33 }
34
35 pub async fn execute(
36 &self,
37 route: &ExecutionRoute,
38 request: HarnessRequest,
39 ) -> Result<HarnessOutcome, HarnessError> {
40 let adapter = if let Some(adapter_name) = &route.adapter {
41 self.adapters
42 .get(adapter_name)
43 .ok_or_else(|| HarnessError::AdapterNotFound(adapter_name.clone()))?
44 .clone()
45 } else {
46 self.adapters
47 .values()
48 .find(|candidate| candidate.kind() == route.harness_kind)
49 .cloned()
50 .ok_or_else(|| {
51 HarnessError::AdapterNotFound(format!("kind::{:?}", route.harness_kind))
52 })?
53 };
54
55 if adapter.kind() != route.harness_kind {
56 return Err(HarnessError::AdapterKindMismatch {
57 adapter: adapter.name().to_owned(),
58 expected: route.harness_kind,
59 actual: adapter.kind(),
60 });
61 }
62
63 return adapter.execute(request).await;
64 }
65}