The Default Agent

The Default agent layer implementation allows an application to get and set values to the state through HTTP calls.

It exposes two endpoints: GET and PUT and does not assume anything about the payload itself. It is up to the application (user) to make sure the payload conforms to the chosen State layer.

Any Agent implementation should choose its own way of exposing ways to get and set values to the state.

Behavior

The behavior of the Default agent is straight forward. It runs a HTTP server with two handlers for getting and setting values.


#![allow(unused)]
fn main() {
async fn handler(state: state::SafeState, req: Request<Body>) -> Result<Response<Body>> {
    Ok(match req.method() {
        &Method::GET => get_handler(state, &req),
        &Method::PUT => set_handler(state, req).await.unwrap(),
        _ => Responses::not_found(None),
    })
}

impl Default {
    async fn server(&self, state: state::SafeState) -> Result<()> {
        let service = make_service_fn(move |_| {
            let state = state.clone();
            async move {
                Ok::<_, Box<dyn StdError + Send + Sync>>(service_fn(move |req| {
                    handler(state.clone(), req)
                }))
            }
        });

        let server = Server::try_bind(&([0, 0, 0, 0], self.port).into())?;
        server.serve(service).await?;

        Ok(())
    }
}

}

The Agent Trait


#![allow(unused)]
fn main() {
pub trait Agent: std::fmt::Debug + Send + Sync {
    fn start<'a>(
        &'a self,
        state: state::SafeState,
    ) -> BoxFuture<'a, Result<(), Box<dyn StdError + Send + Sync>>>;
}
}

The Default agent layer uses the start function to initialize and run the HTTP server.


#![allow(unused)]
fn main() {
fn start<'a>(&'a self, state: state::SafeState) -> BoxFuture<'a, Result<()>> {
    self.server(state).map_err(|e| e.into()).boxed()
}
}