feat(grid-agent): supervise grid sessions (#121)
This commit is contained in:
@@ -4,6 +4,8 @@ use metacrate_grid_agent::{
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
#[cfg(feature = "live-grid")]
|
||||
use std::sync::Arc;
|
||||
|
||||
const MAX_ARGUMENTS: usize = 8;
|
||||
|
||||
@@ -84,9 +86,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
return Ok(());
|
||||
}
|
||||
if config.mode != OperatingMode::OfflineFake {
|
||||
#[cfg(feature = "live-grid")]
|
||||
return run_live(config, options.run_once).await;
|
||||
#[cfg(not(feature = "live-grid"))]
|
||||
return Err(CliError(
|
||||
"this architecture issue starts only the offline backend; live login is owned by a later milestone issue"
|
||||
.into(),
|
||||
"live grid mode requires rebuilding with --features live-grid".into(),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
@@ -133,3 +137,101 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
println!("grid agent stopped cleanly");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "live-grid")]
|
||||
async fn run_live(
|
||||
config: metacrate_grid_agent::AgentConfig,
|
||||
run_once: bool,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
use metacrate_grid_agent::{
|
||||
GridSessionBackend, LibremetaverseClientOwner, SessionObservation, SessionState,
|
||||
SessionSupervisor,
|
||||
};
|
||||
|
||||
let connection = config.grid.clone().ok_or_else(|| {
|
||||
CliError("validated live configuration did not contain a grid connection".into())
|
||||
})?;
|
||||
let owner = LibremetaverseClientOwner::new()?;
|
||||
let backend = owner.session_backend(connection)?;
|
||||
let erased: Arc<dyn GridSessionBackend> = Arc::new(backend);
|
||||
let mut handle = SessionSupervisor::new(
|
||||
erased,
|
||||
config.reconnect,
|
||||
config.limits.control_queue,
|
||||
config.limits.observable_queue,
|
||||
)?
|
||||
.start();
|
||||
|
||||
if run_once {
|
||||
let readiness = tokio::time::timeout(config.timeouts.startup, async {
|
||||
loop {
|
||||
match handle.next_observation().await {
|
||||
Some(SessionObservation::Transition { status, .. }) if status.agent_ready => {
|
||||
return Ok::<(), CliError>(());
|
||||
}
|
||||
Some(SessionObservation::Transition {
|
||||
status:
|
||||
metacrate_grid_agent::SessionStatus {
|
||||
state: SessionState::AuthenticationBlocked,
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
return Err(CliError(
|
||||
"grid authentication/configuration requires operator action".into(),
|
||||
));
|
||||
}
|
||||
Some(_) => {}
|
||||
None => {
|
||||
return Err(CliError(
|
||||
"session supervisor stopped before readiness".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.await;
|
||||
let readiness = match readiness {
|
||||
Ok(result) => result,
|
||||
Err(_) => Err(CliError("timed out waiting for full grid readiness".into())),
|
||||
};
|
||||
if let Err(error) = readiness {
|
||||
handle.shutdown().await?;
|
||||
return Err(error.into());
|
||||
}
|
||||
handle.shutdown().await?;
|
||||
println!("grid agent completed one supervised login/logout cycle");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("grid agent session supervisor started; press Ctrl-C to stop");
|
||||
let mut signal_error = None;
|
||||
loop {
|
||||
tokio::select! {
|
||||
signal = tokio::signal::ctrl_c() => {
|
||||
if let Err(error) = signal {
|
||||
signal_error = Some(error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
event = handle.next_observation() => {
|
||||
let Some(event) = event else { break; };
|
||||
if let SessionObservation::Transition { status, reason, retry_in } = event {
|
||||
println!(
|
||||
"grid session state={} generation={} transport_connected={} agent_ready={} reason={reason:?} retry_in={retry_in:?}",
|
||||
status.state.as_str(),
|
||||
status.generation,
|
||||
status.transport_connected,
|
||||
status.agent_ready,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handle.shutdown().await?;
|
||||
if let Some(error) = signal_error {
|
||||
return Err(error.into());
|
||||
}
|
||||
println!("grid agent stopped cleanly");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user