[Fix] Stability

This commit is contained in:
Alex 2026-07-27 20:37:33 +02:00
commit 14df716cf1
Signed by: alex
SSH key fingerprint: SHA256:D1+Ub8o0v4K5y1JNivW8IxEOelqLSvPmUzBbDIoZkRQ
19 changed files with 483 additions and 405 deletions

View file

@ -8,7 +8,7 @@ use iota_ipc::{
};
use iota_logger::{log, log_command};
use iota_storage::users::user_manager;
use iota_storage::util::config_util::{self, modify_config};
use iota_storage::util::config_util::{self};
use mtp::codec::{CommunicationType, CommunicationValue};
use std::sync::{Arc, Mutex};
use std::time::Duration;
@ -52,10 +52,7 @@ impl CommandRouter {
}
let needs_omikron = matches!(
request,
LocalRequest::CreateUser { .. }
| LocalRequest::RemoveUser { .. }
| LocalRequest::ReconnectOmikron
| LocalRequest::RotateIotaIdentity
LocalRequest::CreateUser { .. } | LocalRequest::RemoveUser { .. }
);
if needs_omikron && !self.services.omikron.is_connected().await {
return ResponseResult::Error(
@ -112,11 +109,33 @@ impl CommandRouter {
)
.await
{
(Some(user), _) => ResponseResult::Ok(ResponsePayload::UserCreated {
Ok(user) => ResponseResult::Ok(ResponsePayload::UserCreated {
user_id: user.user_id,
username: user.username,
}),
_ => ResponseResult::Error(IpcErrorCode::StorageFailure),
Err(error) => {
log!("User creation failed: {error:?}");
match error {
omikron_connector::user_ops::CreateUserError::InvalidUsername => {
ResponseResult::Error(IpcErrorCode::InvalidRequest)
}
omikron_connector::user_ops::CreateUserError::Transport(
omikron_connector::OmikronError::Timeout(_),
) => ResponseResult::Error(IpcErrorCode::Timeout),
omikron_connector::user_ops::CreateUserError::Transport(_) => {
ResponseResult::Error(IpcErrorCode::OmikronUnavailable)
}
omikron_connector::user_ops::CreateUserError::RemoteRejected => {
ResponseResult::Error(IpcErrorCode::Conflict)
}
omikron_connector::user_ops::CreateUserError::LocalPersistence(_) => {
ResponseResult::Error(IpcErrorCode::StorageFailure)
}
omikron_connector::user_ops::CreateUserError::InvalidResponse => {
ResponseResult::Error(IpcErrorCode::InternalFailure)
}
}
}
}
}
LocalRequest::RemoveUser { user_id } => {
@ -139,16 +158,14 @@ impl CommandRouter {
Err(_) => ResponseResult::Error(IpcErrorCode::OmikronUnavailable),
},
LocalRequest::RotateIotaIdentity => {
modify_config(|config| {
config.public_key = None;
config.private_key = None;
config.iota_id = None;
});
match self.services.omikron.reconnect().await {
match self.services.omikron.rotate_identity().await {
Ok(()) => ResponseResult::Ok(ResponsePayload::Acknowledged {
message: "Key pair regenerated and Omikron reconnection requested".into(),
message: "New identity registered with Omikron".into(),
}),
Err(_) => ResponseResult::Error(IpcErrorCode::OmikronUnavailable),
Err(error) => {
log!("Iota identity rotation failed: {}", error);
ResponseResult::Error(IpcErrorCode::OmikronUnavailable)
}
}
}
LocalRequest::RequestProcessExit { intent } => {

View file

@ -61,6 +61,11 @@ impl OmikronClient for InactiveOmikron {
"terms have not been accepted".into(),
))
}
async fn rotate_identity(&self) -> Result<(), OmikronError> {
Err(OmikronError::Disconnected(
"terms have not been accepted".into(),
))
}
async fn is_connected(&self) -> bool {
false
}

View file

@ -29,8 +29,12 @@ impl OmikronClient for FakeOmikron {
self.reconnects.fetch_add(1, Ordering::SeqCst);
Ok(())
}
async fn rotate_identity(&self) -> Result<(), OmikronError> {
self.reconnects.fetch_add(1, Ordering::SeqCst);
Ok(())
}
async fn is_connected(&self) -> bool {
true
false
}
}
@ -43,6 +47,7 @@ async fn reconnect_uses_the_injected_client() {
omikron: fake.clone(),
users: Default::default(),
config: Default::default(),
active: true,
});
let router = CommandRouter::new(
Arc::new(DaemonRuntime::new()),
@ -55,3 +60,29 @@ async fn reconnect_uses_the_injected_client() {
));
assert_eq!(fake.reconnects.load(Ordering::SeqCst), 1);
}
#[tokio::test]
async fn identity_rotation_is_available_while_omikron_is_offline() {
let fake = Arc::new(FakeOmikron {
reconnects: AtomicUsize::new(0),
});
let services = Arc::new(DaemonServices {
omikron: fake.clone(),
users: Default::default(),
config: Default::default(),
active: true,
});
let router = CommandRouter::new(
Arc::new(DaemonRuntime::new()),
services,
Arc::new(Mutex::new(LogBuffer::new(100))),
);
assert!(matches!(
router
.route(1, LocalRequest::RotateIotaIdentity)
.await
.result,
ResponseResult::Ok(_)
));
assert_eq!(fake.reconnects.load(Ordering::SeqCst), 1);
}