1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use std::borrow::{Borrow, Cow};
use std::sync::{RwLock, RwLockWriteGuard};
use stepflow_base::{ObjectStore, IdError, ObjectStoreFiltered};
use stepflow_data::{StateDataFiltered, var::{Var, VarId}};
use stepflow_step::Step;
use stepflow_action::{ActionResult, Action, ActionId};
use super::{Error};


/// A wrapper to make it easier to access this ObjectStore that uses interior mutability.
#[derive(Debug)]
pub struct ActionObjectStore {
  object_store: RwLock<ObjectStore<Box<dyn Action + Sync + Send>, ActionId>>,
}

impl ActionObjectStore {
  pub fn with_capacity(capacity: usize) -> ActionObjectStore {
    ActionObjectStore {
      object_store: RwLock::new(ObjectStore::with_capacity(capacity)),
    }
  }

  fn action_store_write(&self) 
      -> Result<RwLockWriteGuard<ObjectStore<Box<dyn Action + Sync + Send>, ActionId>>, Error>
  {
    let store = self
      .object_store
      .try_write()
      .map_err(|_e| Error::Other)?;
    Ok(store)
  }

  pub fn reserve_id(&self) -> Result<ActionId, Error> {
    self.action_store_write()
     .map(|mut store| store.reserve_id())
  }

  pub fn insert_new<CB>(&self, cb: CB) -> Result<ActionId, Error>
      where CB: FnOnce(ActionId) -> Result<Box<dyn Action + Sync + Send>, IdError<ActionId>>
  {
    self.action_store_write()
      .and_then(|mut store| {
        store.insert_new(cb).map_err(|e| Error::ActionId(e))
      })
  }

  pub fn insert_new_named<CB, STR>(&self, name: STR, cb: CB) -> Result<ActionId, Error>
      where CB: FnOnce(ActionId) -> Result<Box<dyn Action + Sync + Send>, IdError<ActionId>>,
            STR: Into<Cow<'static, str>>
  {
    self.action_store_write()
      .and_then(|mut store| {
        store.insert_new_named(name, cb).map_err(|e| Error::ActionId(e))
      })
  }

  pub fn register(&self, object: Box<dyn Action + Sync + Send>) -> Result<ActionId, Error> {
    self.action_store_write()
      .and_then(|mut store| {
        store.register(object).map_err(|e| Error::ActionId(e))
      })
  }

  pub fn register_named<STR>(&self, name: String, object: Box<dyn Action + Sync + Send>) -> Result<ActionId, Error>
      where STR: Into<Cow<'static, str>>
  {
    self.action_store_write()
      .and_then(|mut store| {
        store.register_named(name, object).map_err(|e| Error::ActionId(e))
      })
  }


  pub fn id_from_name<STR>(&self, name: STR) -> Result<ActionId, Error>
      where STR: Into<Cow<'static, str>>
  {
    let name: Cow<'static, str> = name.into();
    self.action_store_write()
      .and_then(|store| {
        store.id_from_name(name.borrow())
          .map(|id| id.clone())
          .ok_or_else(|| Error::ActionId(IdError::NoSuchName(name.into_owned())))
      })
  }

  pub fn name_from_id(&self, action_id: &ActionId) -> Result<String, Error> {
    self.action_store_write()
      .and_then(|store| {
        store.name_from_id(action_id)
          .map(|name| name.to_owned())
          .ok_or_else(|| Error::ActionId(IdError::IdMissing(action_id.clone())))
      })
  }

  pub fn start_action(&self, id: &ActionId, step: &Step, step_name: Option<&str>, step_data: &StateDataFiltered, vars: &ObjectStoreFiltered<Box<dyn Var + Send + Sync>, VarId>)
      -> Result<ActionResult, Error>
  {
    self.action_store_write()
      .and_then(|mut store| {
        let action = store.get_mut(id).ok_or_else(|| Error::ActionId(IdError::IdMissing(id.clone())))?;
        action.start(&step, step_name, &step_data, &vars)
          .map_err(|e| e.into())
      })
  }
}