Skip to main content

Reaction

Trait Reaction 

Source
pub trait Reaction: Send + Sync {
    // Required methods
    fn id(&self) -> &str;
    fn type_name(&self) -> &str;
    fn properties(&self) -> HashMap<String, Value>;
    fn query_ids(&self) -> Vec<String>;
    fn initialize<'life0, 'async_trait>(
        &'life0 self,
        context: ReactionRuntimeContext,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn start<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn stop<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn status<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = ComponentStatus> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;

    // Provided method
    fn auto_start(&self) -> bool { ... }
}
Expand description

Reaction traits for implementing reaction plugins Trait defining the interface for all reaction implementations.

This is the core abstraction that all reaction plugins must implement. drasi-lib only interacts with reactions through this trait - it has no knowledge of specific plugin types or their configurations.

§Lifecycle

Reactions follow this lifecycle:

  1. Created by plugin code with configuration
  2. Added to DrasiLib via add_reaction() - dependencies injected automatically
  3. Started via start() (auto-start or manual based on auto_start())
  4. Stopped via stop() when no longer needed

§Subscription Model

Reactions manage their own subscriptions to queries using the broadcast channel pattern:

  • QueryProvider is injected via inject_query_provider() at add time
  • Reactions access queries via query_provider.get_query_instance()
  • For each query, reactions call query.subscribe(reaction_id)
  • Each subscription provides a broadcast receiver for that query’s results
  • Reactions use a priority queue to process results from multiple queries in timestamp order

§Example Implementation

use drasi_lib::{Reaction, QueryProvider};
use drasi_lib::reactions::{ReactionBase, ReactionBaseParams};
use drasi_lib::context::ReactionRuntimeContext;

pub struct MyReaction {
    base: ReactionBase,
    // Plugin-specific fields
}

impl MyReaction {
    pub fn new(config: MyReactionConfig) -> Self {
        let params = ReactionBaseParams::new(&config.id, config.queries.clone())
            .with_priority_queue_capacity(config.queue_capacity);

        Self {
            base: ReactionBase::new(params),
        }
    }
}

#[async_trait]
impl Reaction for MyReaction {
    fn id(&self) -> &str {
        &self.base.id
    }

    fn type_name(&self) -> &str {
        "my-reaction"
    }

    fn query_ids(&self) -> Vec<String> {
        self.base.queries.clone()
    }

    async fn initialize(&self, context: ReactionRuntimeContext) {
        self.base.initialize(context).await;
    }

    async fn start(&self) -> Result<()> {
        self.base.subscribe_to_queries().await?;
        // ... start processing
        Ok(())
    }

    // ... implement other methods
}

Required Methods§

Source

fn id(&self) -> &str

Get the reaction’s unique identifier

Source

fn type_name(&self) -> &str

Get the reaction type name (e.g., “http”, “log”, “sse”)

Source

fn properties(&self) -> HashMap<String, Value>

Get the reaction’s configuration properties for inspection

This returns a HashMap representation of the reaction’s configuration for use in APIs and inspection. The actual typed configuration is owned by the plugin - this is just for external visibility.

Source

fn query_ids(&self) -> Vec<String>

Get the list of query IDs this reaction subscribes to

Source

fn initialize<'life0, 'async_trait>( &'life0 self, context: ReactionRuntimeContext, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Initialize the reaction with runtime context.

This method is called automatically by DrasiLib when the reaction is added via add_reaction(). Plugin developers do not need to call this directly.

The context provides access to:

  • reaction_id: The reaction’s unique identifier
  • event_tx: Channel for reporting component lifecycle events
  • state_store: Optional persistent state storage
  • query_provider: Access to query instances for subscription

Implementation should delegate to self.base.initialize(context).await.

Source

fn start<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Start the reaction

The reaction should:

  1. Subscribe to all configured queries (using injected QueryProvider)
  2. Start its processing loop
  3. Update its status to Running

Note: QueryProvider is already available via inject_query_provider() which is called when the reaction is added to DrasiLib.

Source

fn stop<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Stop the reaction, cleaning up all subscriptions and tasks

Source

fn status<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = ComponentStatus> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Get the current status of the reaction

Provided Methods§

Source

fn auto_start(&self) -> bool

Whether this reaction should auto-start when DrasiLib starts

Default is true to match query behavior. Override to return false if this reaction should only be started manually via start_reaction().

Trait Implementations§

Source§

impl Reaction for Box<dyn Reaction + 'static>

Blanket implementation of Reaction for Box<dyn Reaction>

This allows boxed trait objects to be used with methods expecting impl Reaction.

Source§

fn id(&self) -> &str

Get the reaction’s unique identifier
Source§

fn type_name(&self) -> &str

Get the reaction type name (e.g., “http”, “log”, “sse”)
Source§

fn properties(&self) -> HashMap<String, Value>

Get the reaction’s configuration properties for inspection Read more
Source§

fn query_ids(&self) -> Vec<String>

Get the list of query IDs this reaction subscribes to
Source§

fn auto_start(&self) -> bool

Whether this reaction should auto-start when DrasiLib starts Read more
Source§

fn initialize<'life0, 'async_trait>( &'life0 self, context: ReactionRuntimeContext, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Initialize the reaction with runtime context. Read more
Source§

fn start<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Start the reaction Read more
Source§

fn stop<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Stop the reaction, cleaning up all subscriptions and tasks
Source§

fn status<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = ComponentStatus> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Get the current status of the reaction

Implementations on Foreign Types§

Source§

impl Reaction for Box<dyn Reaction + 'static>

Blanket implementation of Reaction for Box<dyn Reaction>

This allows boxed trait objects to be used with methods expecting impl Reaction.

Source§

fn id(&self) -> &str

Source§

fn type_name(&self) -> &str

Source§

fn properties(&self) -> HashMap<String, Value>

Source§

fn query_ids(&self) -> Vec<String>

Source§

fn auto_start(&self) -> bool

Source§

fn initialize<'life0, 'async_trait>( &'life0 self, context: ReactionRuntimeContext, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn start<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn stop<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn status<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = ComponentStatus> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Implementors§