mod pending;
use crate::core::contracts::instance::ObservedState;
use crate::core::{domain::Scope, error::Result, output::Envelope};
use crate::messaging::session::{acknowledge_identity, remember_identity, status_data};
use crate::storage::state::{Installation, Instance, Store};
use crate::transport::client::{Backend, inspect_with_version_guard};
pub(super) use pending::execute_pending;
use std::time::Instant;
pub(super) fn execute<B: Backend>(
store: &Store,
instance: &Instance,
installation: &Installation,
backend: &B,
deadline: Instant,
pending_observation: impl FnOnce() -> Result<Envelope>,
) -> Result<Envelope> {
let info = match inspect_with_version_guard(backend, deadline, |version| {
crate::messaging::session::validate_version_value(version, &installation.version)
}) {
Err(error)
if matches!(instance.state.as_str(), "starting" | "login_required")
&& matches!(error.code, "BACKEND_NOT_LISTENING" | "AUTH_REQUIRED") =>
{
return pending_observation();
}
result => result?,
};
let scope = Scope {
instance_id: instance.id.clone(),
account: info.account.clone(),
};
if matches!(instance.state.as_str(), "starting" | "login_required") {
let changed = crate::messaging::session::confirm_login(
store,
instance,
installation,
&info,
deadline,
)?;
let mut data = status_data(&info);
if changed {
data.state = ObservedState::AccountChanged;
}
return Ok(Envelope::typed(data).scoped(scope));
}
if instance
.account
.as_ref()
.is_some_and(|account| account != &info.account)
{
acknowledge_identity(store, instance, &info.account, deadline)?;
let mut data = status_data(&info);
data.state = ObservedState::AccountChanged;
data.nickname = None;
return Ok(Envelope::typed(data).scoped(scope));
}
remember_identity(store, instance, &info.account, deadline)?;
Ok(Envelope::typed(status_data(&info)).scoped(scope))
}