Skip to content

What is the intended mechanism for an incoming-handler to configure subscription topics? #33

@andrew-goldie

Description

@andrew-goldie

In implementing the 0.2.0-draft WIT I had some problems understanding how to allow a guest subscriber to configure the topics the underlying provider will listen on. I ended up extending the incoming-handler interface thus:

interface incoming-handler {
    use types.{message, error, topic};

    /// Whenever this guest receives a message in one of the subscribed topics, the message is
    /// sent to this handler. The guest is responsible for matching on the topic and handling the
    /// message accordingly. Implementors (such as hosts) calling this interface should make their
    /// own decisions on how to handle errors returned from this function.
    handle: func(message: message) -> result<_, error>;

    /// Server configuration.
    /// 
    /// This can be extended to include other configuration options in the
    /// future.
    record server-configuration {
        /// Subscription topics
        topics: list<topic>,
    }

    /// Configure is called by the runtime to get the server's runtime
    /// configuration.
    configure: func() -> result<server-configuration, error>;
}

A sample guest would look like...

struct MessagingGuest;

impl Guest for MessagingGuest {
    fn handle(msg: Message) -> Result<(), Error> {
        let Some(topic) = &msg.topic() else {
            return Ok(());
        };
        // do stuff conditional on topic
        Ok(())
    }

    fn configure() -> Result<ServerConfiguration, Error> {
        Ok(ServerConfiguration {
            topics: vec!["a", "b", "c", "d"].into_iter().map(|s| s.to_string()).collect(),
        })
    }
}

Then when setting up the component in the runtime our calls look something like...

use wasmtime::Store;
use wasmtime::component::InstancePre;

use crate::messaging::generated::MessagingPre;
//...
    let mut store = Store::new(pre.engine(), Ctx::new(resources.clone(), pre.clone()));
    let msg_pre = MessagingPre::new(pre.clone())?;
    let msg = msg_pre.instantiate_async(&mut store).await?;
    let config = msg.wasi_messaging_incoming_handler().call_configure(&mut store).await??; 

   // Now I can configure NATS subscription subjects, spawn a thread for each message
   // and pass the message (as a resource handle) to the incoming handler's handle function.

Apologies if the code snippets make my simple question more complicated than necessary. All I really want to understand is the intended pattern to ensure the guest only listens to topics it's interested in without hard-coding it into the component.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions