fix(tui): improve reliability of status updates
This commit is contained in:
parent
eb42745383
commit
2a836b42b7
9 changed files with 61 additions and 48 deletions
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
|
||||||
use tracing::warn;
|
use tracing::{warn, Instrument};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
repo::{
|
repo::{
|
||||||
|
@ -34,11 +34,12 @@ impl Handler<AdvanceNext> for RepoActor {
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
|
|
||||||
let (commit, force) = find_next_commit_on_dev(&next, &main, &dev_commit_history);
|
let (commit, force) = find_next_commit_on_dev(&next, &main, &dev_commit_history);
|
||||||
self.update_tui(RepoUpdate::AdvancingNext {
|
if let Some(commit) = &commit {
|
||||||
commit: commit.clone(),
|
self.update_tui(RepoUpdate::AdvancingNext {
|
||||||
force: force.clone(),
|
commit: commit.clone(),
|
||||||
});
|
force: force.clone(),
|
||||||
|
});
|
||||||
|
};
|
||||||
match advance_next(
|
match advance_next(
|
||||||
commit,
|
commit,
|
||||||
force,
|
force,
|
||||||
|
@ -49,10 +50,20 @@ impl Handler<AdvanceNext> for RepoActor {
|
||||||
) {
|
) {
|
||||||
Ok(message_token) => {
|
Ok(message_token) => {
|
||||||
// pause to allow any CI checks to be started
|
// pause to allow any CI checks to be started
|
||||||
std::thread::sleep(self.sleep_duration);
|
let sleep_duration = self.sleep_duration;
|
||||||
do_send(&addr, ValidateRepo::new(message_token), self.log.as_ref());
|
let log = self.log.clone();
|
||||||
|
async move {
|
||||||
|
std::thread::sleep(sleep_duration);
|
||||||
|
do_send(&addr, ValidateRepo::new(message_token), log.as_ref());
|
||||||
|
}
|
||||||
|
.in_current_span()
|
||||||
|
.into_actor(self)
|
||||||
|
.wait(ctx);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("advance next: {err}");
|
||||||
|
self.alert_tui(err.to_string());
|
||||||
}
|
}
|
||||||
Err(err) => warn!("advance next: {err}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
|
||||||
use git_next_core::git::{forge::commit::Status, graph, UserNotification};
|
use git_next_core::git::{forge::commit::Status, graph, UserNotification};
|
||||||
use tracing::debug;
|
use tracing::{debug, Instrument as _};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
repo::{
|
repo::{
|
||||||
delay_send, do_send, logger,
|
do_send, logger,
|
||||||
messages::{AdvanceMain, ReceiveCIStatus, ValidateRepo},
|
messages::{AdvanceMain, ReceiveCIStatus, ValidateRepo},
|
||||||
notify_user, RepoActor,
|
notify_user, RepoActor,
|
||||||
},
|
},
|
||||||
|
@ -53,12 +53,16 @@ impl Handler<ReceiveCIStatus> for RepoActor {
|
||||||
},
|
},
|
||||||
log.as_ref(),
|
log.as_ref(),
|
||||||
);
|
);
|
||||||
delay_send(
|
async move {
|
||||||
&addr,
|
debug!("sleeping before retrying...");
|
||||||
sleep_duration,
|
logger(log.as_ref(), "before sleep");
|
||||||
ValidateRepo::new(message_token),
|
actix_rt::time::sleep(sleep_duration).await;
|
||||||
self.log.as_ref(),
|
logger(log.as_ref(), "after sleep");
|
||||||
);
|
do_send(&addr, ValidateRepo::new(message_token), log.as_ref());
|
||||||
|
}
|
||||||
|
.in_current_span()
|
||||||
|
.into_actor(self)
|
||||||
|
.wait(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
|
||||||
use tracing::{debug, instrument, Instrument as _};
|
use tracing::{info, instrument, Instrument as _};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
repo::{
|
repo::{
|
||||||
|
@ -13,6 +13,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use git_next_core::git::{
|
use git_next_core::git::{
|
||||||
|
push::Force,
|
||||||
validation::positions::{validate, Error, Positions},
|
validation::positions::{validate, Error, Positions},
|
||||||
UserNotification,
|
UserNotification,
|
||||||
};
|
};
|
||||||
|
@ -74,11 +75,18 @@ impl Handler<ValidateRepo> for RepoActor {
|
||||||
},
|
},
|
||||||
git_log,
|
git_log,
|
||||||
)) => {
|
)) => {
|
||||||
debug!(%main, %next, %dev, "positions");
|
info!(%main, %next, %dev, "positions");
|
||||||
self.update_tui_log(git_log);
|
self.update_tui_log(git_log);
|
||||||
if next_is_valid && next != main {
|
if next_is_valid && next != main {
|
||||||
|
info!("Checking CI");
|
||||||
|
self.update_tui(RepoUpdate::CheckingCI);
|
||||||
do_send(&ctx.address(), CheckCIStatus::new(next), self.log.as_ref());
|
do_send(&ctx.address(), CheckCIStatus::new(next), self.log.as_ref());
|
||||||
} else if next != dev {
|
} else if next != dev {
|
||||||
|
info!("Advance next");
|
||||||
|
self.update_tui(RepoUpdate::AdvancingNext {
|
||||||
|
commit: next.clone(),
|
||||||
|
force: Force::No,
|
||||||
|
});
|
||||||
do_send(
|
do_send(
|
||||||
&ctx.address(),
|
&ctx.address(),
|
||||||
AdvanceNext::new(AdvanceNextPayload {
|
AdvanceNext::new(AdvanceNextPayload {
|
||||||
|
@ -89,10 +97,12 @@ impl Handler<ValidateRepo> for RepoActor {
|
||||||
self.log.as_ref(),
|
self.log.as_ref(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
info!("do nothing");
|
||||||
self.update_tui(RepoUpdate::Okay { main, next, dev });
|
self.update_tui(RepoUpdate::Okay { main, next, dev });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(Error::Retryable(message)) => {
|
Err(Error::Retryable(message)) => {
|
||||||
|
info!(?message, "Retryable");
|
||||||
self.alert_tui(format!("[retryable: {message}]"));
|
self.alert_tui(format!("[retryable: {message}]"));
|
||||||
logger(self.log.as_ref(), message);
|
logger(self.log.as_ref(), message);
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
|
@ -100,7 +110,7 @@ impl Handler<ValidateRepo> for RepoActor {
|
||||||
let sleep_duration = self.sleep_duration;
|
let sleep_duration = self.sleep_duration;
|
||||||
let log = self.log.clone();
|
let log = self.log.clone();
|
||||||
async move {
|
async move {
|
||||||
debug!("sleeping before retrying...");
|
info!("sleeping before retrying...");
|
||||||
logger(log.as_ref(), "before sleep");
|
logger(log.as_ref(), "before sleep");
|
||||||
actix_rt::time::sleep(sleep_duration).await;
|
actix_rt::time::sleep(sleep_duration).await;
|
||||||
logger(log.as_ref(), "after sleep");
|
logger(log.as_ref(), "after sleep");
|
||||||
|
@ -111,6 +121,7 @@ impl Handler<ValidateRepo> for RepoActor {
|
||||||
.wait(ctx);
|
.wait(ctx);
|
||||||
}
|
}
|
||||||
Err(Error::UserIntervention(user_notification)) => {
|
Err(Error::UserIntervention(user_notification)) => {
|
||||||
|
info!(?user_notification, "User Intervention");
|
||||||
self.alert_tui(format!("[USER INTERVENTION: {user_notification}]"));
|
self.alert_tui(format!("[USER INTERVENTION: {user_notification}]"));
|
||||||
if let UserNotification::CICheckFailed { log, .. }
|
if let UserNotification::CICheckFailed { log, .. }
|
||||||
| UserNotification::DevNotBasedOnMain { log, .. } = &user_notification
|
| UserNotification::DevNotBasedOnMain { log, .. } = &user_notification
|
||||||
|
@ -124,6 +135,7 @@ impl Handler<ValidateRepo> for RepoActor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(Error::NonRetryable(message)) => {
|
Err(Error::NonRetryable(message)) => {
|
||||||
|
info!(?message, "NonRetryable");
|
||||||
self.alert_tui(format!("[Error: {message}]"));
|
self.alert_tui(format!("[Error: {message}]"));
|
||||||
logger(self.log.as_ref(), message);
|
logger(self.log.as_ref(), message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ use crate::{
|
||||||
};
|
};
|
||||||
use derive_more::Deref;
|
use derive_more::Deref;
|
||||||
use kxio::network::Network;
|
use kxio::network::Network;
|
||||||
use std::time::Duration;
|
|
||||||
use tracing::{info, instrument, warn, Instrument};
|
use tracing::{info, instrument, warn, Instrument};
|
||||||
|
|
||||||
use git_next_core::{
|
use git_next_core::{
|
||||||
|
@ -172,19 +171,6 @@ impl Actor for RepoActor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delay_send<M>(addr: &Addr<RepoActor>, delay: Duration, msg: M, log: Option<&ActorLog>)
|
|
||||||
where
|
|
||||||
M: actix::Message + Send + 'static + std::fmt::Debug,
|
|
||||||
RepoActor: actix::Handler<M>,
|
|
||||||
<M as actix::Message>::Result: Send,
|
|
||||||
{
|
|
||||||
let log_message = format!("send-after-delay: {msg:?}");
|
|
||||||
tracing::debug!(log_message);
|
|
||||||
logger(log, log_message);
|
|
||||||
std::thread::sleep(delay);
|
|
||||||
do_send(addr, msg, log);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn do_send<M>(addr: &Addr<RepoActor>, msg: M, log: Option<&ActorLog>)
|
pub fn do_send<M>(addr: &Addr<RepoActor>, msg: M, log: Option<&ActorLog>)
|
||||||
where
|
where
|
||||||
M: actix::Message + Send + 'static + std::fmt::Debug,
|
M: actix::Message + Send + 'static + std::fmt::Debug,
|
||||||
|
@ -192,7 +178,7 @@ where
|
||||||
<M as actix::Message>::Result: Send,
|
<M as actix::Message>::Result: Send,
|
||||||
{
|
{
|
||||||
let log_message = format!("send: {msg:?}");
|
let log_message = format!("send: {msg:?}");
|
||||||
tracing::debug!(log_message);
|
info!(log_message);
|
||||||
logger(log, log_message);
|
logger(log, log_message);
|
||||||
if cfg!(not(test)) {
|
if cfg!(not(test)) {
|
||||||
// #[cfg(not(test))]
|
// #[cfg(not(test))]
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::repo::messages::AdvanceNextPayload;
|
use crate::repo::messages::AdvanceNextPayload;
|
||||||
|
|
||||||
//
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[actix::test]
|
#[test_log::test(actix::test)]
|
||||||
async fn should_fetch_then_push_then_revalidate() -> TestResult {
|
async fn should_fetch_then_push_then_revalidate() -> TestResult {
|
||||||
//given
|
//given
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
|
@ -41,14 +43,11 @@ async fn should_fetch_then_push_then_revalidate() -> TestResult {
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.await?;
|
.await?;
|
||||||
|
actix_rt::time::sleep(Duration::from_millis(1)).await;
|
||||||
System::current().stop();
|
System::current().stop();
|
||||||
|
|
||||||
//then
|
//then
|
||||||
tracing::debug!(?log, "");
|
tracing::debug!(?log, "");
|
||||||
log.read().map_err(|e| e.to_string()).map(|l| {
|
log.require_message_containing("send: ValidateRepo")?;
|
||||||
assert!(l
|
|
||||||
.iter()
|
|
||||||
.any(|message| message.contains("send: ValidateRepo")));
|
|
||||||
})?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
//
|
//
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -79,7 +81,7 @@ async fn when_fail_should_recheck_after_delay() -> TestResult {
|
||||||
git::forge::commit::Status::Fail,
|
git::forge::commit::Status::Fail,
|
||||||
)))
|
)))
|
||||||
.await?;
|
.await?;
|
||||||
actix_rt::time::sleep(std::time::Duration::from_millis(2)).await;
|
actix_rt::time::sleep(Duration::from_millis(10)).await;
|
||||||
System::current().stop();
|
System::current().stop();
|
||||||
|
|
||||||
//then
|
//then
|
||||||
|
|
|
@ -70,7 +70,7 @@ pub enum RepoUpdate {
|
||||||
},
|
},
|
||||||
CheckingCI,
|
CheckingCI,
|
||||||
AdvancingNext {
|
AdvancingNext {
|
||||||
commit: Option<git::Commit>,
|
commit: git::Commit,
|
||||||
force: git::push::Force,
|
force: git::push::Force,
|
||||||
},
|
},
|
||||||
AdvancingMain {
|
AdvancingMain {
|
||||||
|
|
|
@ -47,10 +47,9 @@ impl Handler<ServerUpdate> for Tui {
|
||||||
RepoUpdate::CheckingCI => {
|
RepoUpdate::CheckingCI => {
|
||||||
repo_state.update_message("Checking CI status");
|
repo_state.update_message("Checking CI status");
|
||||||
}
|
}
|
||||||
RepoUpdate::AdvancingNext {
|
RepoUpdate::AdvancingNext { commit, force: _ } => {
|
||||||
commit: _,
|
repo_state.update_message(format!("advancing next to {commit}"));
|
||||||
force: _,
|
}
|
||||||
} => (),
|
|
||||||
RepoUpdate::AdvancingMain { commit } => {
|
RepoUpdate::AdvancingMain { commit } => {
|
||||||
repo_state.update_message(format!("advancing main to {commit}"));
|
repo_state.update_message(format!("advancing main to {commit}"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,12 +233,12 @@ impl RepoState {
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub fn update_message(&mut self, msg: impl Into<String> + std::fmt::Debug) {
|
pub fn update_message(&mut self, msg: impl Into<String> + std::fmt::Debug) {
|
||||||
tracing::info!("new tui message");
|
|
||||||
let msg: String = msg.into();
|
let msg: String = msg.into();
|
||||||
match self {
|
match self {
|
||||||
Self::Identified { message, .. }
|
Self::Identified { message, .. }
|
||||||
| Self::Configured { message, .. }
|
| Self::Configured { message, .. }
|
||||||
| Self::Ready { message, .. } => {
|
| Self::Ready { message, .. } => {
|
||||||
|
info!(?msg, "updating ui");
|
||||||
*message = msg;
|
*message = msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue