1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//
use std::collections::BTreeMap;

use actix::prelude::*;
use derive_more::Constructor;
use git_next_config::{ForgeAlias, RepoAlias};
use git_next_repo_actor::messages::WebhookNotification;
use tracing::info;

pub struct WebhookRouter {
    span: tracing::Span,
    recipients: BTreeMap<ForgeAlias, BTreeMap<RepoAlias, Recipient<WebhookNotification>>>,
}
impl Default for WebhookRouter {
    fn default() -> Self {
        Self::new()
    }
}
impl WebhookRouter {
    pub fn new() -> Self {
        let span = tracing::info_span!("WebhookRouter");
        Self {
            span,
            recipients: Default::default(),
        }
    }
}
impl Actor for WebhookRouter {
    type Context = Context<Self>;
}

impl Handler<WebhookNotification> for WebhookRouter {
    type Result = ();

    fn handle(&mut self, msg: WebhookNotification, _ctx: &mut Self::Context) -> Self::Result {
        let _gaurd = self.span.enter();
        let forge_alias = msg.forge_alias();
        let repo_alias = msg.repo_alias();
        tracing::debug!(forge = %forge_alias, repo = %repo_alias, "Router...");
        let Some(forge_repos) = self.recipients.get(forge_alias) else {
            tracing::warn!(forge = %forge_alias, "No forge repos found");
            return;
        };
        let Some(recipient) = forge_repos.get(repo_alias) else {
            tracing::debug!(forge = %forge_alias, repo = %repo_alias, "No recipient found");
            return;
        };
        recipient.do_send(msg);
    }
}

#[derive(Message, Constructor)]
#[rtype(result = "()")]
pub struct AddWebhookRecipient {
    pub forge_alias: ForgeAlias,
    pub repo_alias: RepoAlias,
    pub recipient: Recipient<WebhookNotification>,
}
impl Handler<AddWebhookRecipient> for WebhookRouter {
    type Result = ();

    fn handle(&mut self, msg: AddWebhookRecipient, _ctx: &mut Self::Context) -> Self::Result {
        let _gaurd = self.span.enter();
        info!(forge = %msg.forge_alias, repo = %msg.repo_alias, "Register Recipient");
        if !self.recipients.contains_key(&msg.forge_alias) {
            self.recipients
                .insert(msg.forge_alias.clone(), BTreeMap::new());
        }
        self.recipients
            .get_mut(&msg.forge_alias)
            .map(|repos| repos.insert(msg.repo_alias, msg.recipient));
    }
}