use serde_json::Value;
use std::sync::Arc;
use super::ConsumerCtx;
use crate::boundary::reply::Reply;
use crate::boundary::{Gesture, Query};
enum Subject {
Tail(String),
Login(String),
Attention,
}
impl ConsumerCtx {
pub fn follow(
&self,
peer: &crate::registry::Peer,
request: &Value,
) -> Option<Box<dyn Iterator<Item = Value>>> {
let Ok(gesture) = crate::boundary::codec::decode(request) else {
return None;
};
if !peer.grade.admits(&gesture) {
return None;
}
let (named, subject) = match gesture {
Gesture::Ask(Query::Follow { workspace, agent }) => {
(Some(workspace), Subject::Tail(agent))
}
Gesture::Ask(Query::LoginTail {
workspace,
provider,
}) => (Some(workspace), Subject::Login(provider)),
Gesture::Ask(Query::Attention) => (None, Subject::Attention),
_ => return None,
};
let client = &peer.client;
let scope = crate::registry::registered(&self.state_root, client);
let (deps, _, _) = self.deps(client, Some(&scope));
let ws = match named {
Some(name) => deps.snapshot.ws_path(&name).ok()?,
None => std::path::PathBuf::new(),
};
let frames: Box<dyn Iterator<Item = Reply>> = match subject {
Subject::Tail(agent) => {
let agent =
crate::boundary::address::resolve_agent(&deps.snapshot, &ws, Some(agent))
.ok()?;
Box::new(crate::boundary::follow::Follow::new(
self.cell.clone(),
ws,
agent,
))
}
Subject::Login(provider) => Box::new(crate::boundary::login::Lane::new(
deps.caller.logins.clone(),
ws,
provider,
)),
Subject::Attention => Box::new(crate::boundary::attend::Attend::new(
self.cell.clone(),
scope,
self.ui_path.clone(),
Arc::clone(&self.clock),
)),
};
Some(Box::new(
frames.map(|reply| crate::boundary::reply::encode(&reply)),
))
}
}