git-next/crates/repo-actor/src/lib.rs

145 lines
4.4 KiB
Rust
Raw Normal View History

mod branch;
pub mod handlers;
mod load;
pub mod messages;
2024-04-09 10:44:01 +01:00
2024-05-14 07:59:31 +01:00
#[cfg(test)]
mod tests;
use std::time::Duration;
2024-04-09 10:44:01 +01:00
use actix::prelude::*;
2024-05-23 16:50:36 +01:00
2024-06-27 21:10:41 +01:00
use derive_more::Deref;
use git_next_config as config;
use git_next_git as git;
2024-05-23 16:50:36 +01:00
2024-04-09 10:44:01 +01:00
use kxio::network::Network;
use tracing::{info, warn, Instrument};
2024-06-27 21:10:41 +01:00
#[derive(Clone, Debug, Default)]
pub struct RepoActorLog(std::sync::Arc<std::sync::RwLock<Vec<String>>>);
2024-06-27 21:10:41 +01:00
impl Deref for RepoActorLog {
type Target = std::sync::Arc<std::sync::RwLock<Vec<String>>>;
2024-06-27 21:10:41 +01:00
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// An actor that represents a Git Repository.
///
/// When this actor is started it is sent the [CloneRepo] message.
2024-06-27 21:10:41 +01:00
#[derive(Debug, derive_more::Display, derive_with::With)]
#[display("{}:{}:{}", generation, repo_details.forge.forge_alias(), repo_details.repo_alias)]
2024-04-09 10:44:01 +01:00
pub struct RepoActor {
sleep_duration: std::time::Duration,
generation: git::Generation,
message_token: messages::MessageToken,
repo_details: git::RepoDetails,
webhook: config::server::Webhook,
webhook_id: Option<config::WebhookId>, // INFO: if [None] then no webhook is configured
webhook_auth: Option<config::WebhookAuth>, // INFO: if [None] then no webhook is configured
last_main_commit: Option<git::Commit>,
last_next_commit: Option<git::Commit>,
last_dev_commit: Option<git::Commit>,
repository_factory: Box<dyn git::repository::RepositoryFactory>,
open_repository: Option<Box<dyn git::repository::OpenRepositoryLike>>,
2024-04-09 10:44:01 +01:00
net: Network,
forge: Box<dyn git::ForgeLike>,
log: Option<RepoActorLog>,
2024-04-09 10:44:01 +01:00
}
impl RepoActor {
pub fn new(
repo_details: git::RepoDetails,
forge: Box<dyn git::ForgeLike>,
webhook: config::server::Webhook,
generation: git::Generation,
net: Network,
repository_factory: Box<dyn git::repository::RepositoryFactory>,
sleep_duration: std::time::Duration,
) -> Self {
let message_token = messages::MessageToken::default();
2024-04-09 10:44:01 +01:00
Self {
generation,
message_token,
repo_details,
webhook,
webhook_id: None,
webhook_auth: None,
last_main_commit: None,
last_next_commit: None,
last_dev_commit: None,
repository_factory,
open_repository: None,
forge,
net,
sleep_duration,
log: None,
2024-04-09 10:44:01 +01:00
}
}
}
impl Actor for RepoActor {
type Context = Context<Self>;
#[tracing::instrument(name = "RepoActor::stopping", skip_all, fields(repo = %self.repo_details))]
fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
tracing::debug!("stopping");
info!("Checking webhook");
match self.webhook_id.take() {
Some(webhook_id) => {
tracing::warn!("stopping - unregistering webhook");
info!(%webhook_id, "Unregistring webhook");
let forge = self.forge.duplicate();
async move {
if let Err(err) = forge.unregister_webhook(&webhook_id).await {
warn!("unregistering webhook: {err}");
}
}
.in_current_span()
.into_actor(self)
.wait(ctx);
Running::Continue
}
None => Running::Stop,
}
}
2024-04-09 10:44:01 +01:00
}
pub fn delay_send<M>(
addr: Addr<RepoActor>,
delay: Duration,
msg: M,
log: &Option<crate::RepoActorLog>,
) 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<crate::RepoActorLog>)
where
M: actix::Message + Send + 'static + std::fmt::Debug,
RepoActor: actix::Handler<M>,
<M as actix::Message>::Result: Send,
{
let log_message = format!("send: {:?}", msg);
tracing::debug!(log_message);
logger(log, log_message);
#[cfg(not(test))]
_addr.do_send(msg)
}
pub fn logger(log: &Option<crate::RepoActorLog>, message: impl Into<String>) {
if let Some(log) = log {
let message: String = message.into();
tracing::debug!(message);
let _ = log.write().map(|mut l| l.push(message));
}
}