Skip to main content

github_bot_sdk/events/
session.rs

1//! Session management for ordered event processing.
2
3use super::processor::SessionIdStrategy;
4use super::{EntityType, EventEnvelope};
5
6/// Manages session IDs for ordered event processing.
7///
8/// The session manager provides different strategies for grouping related
9/// events to ensure they are processed in order. This is critical for
10/// maintaining consistency when handling sequences of related events.
11///
12/// # Examples
13///
14/// ```rust
15/// use github_bot_sdk::events::{SessionManager, SessionIdStrategy};
16///
17/// let manager = SessionManager::new(SessionIdStrategy::Entity);
18/// // Use with event processing...
19/// ```
20pub struct SessionManager {
21    strategy: SessionIdStrategy,
22}
23
24impl SessionManager {
25    /// Create a new session manager with the given strategy.
26    pub fn new(strategy: SessionIdStrategy) -> Self {
27        Self { strategy }
28    }
29
30    /// Generate a session ID for an event envelope.
31    ///
32    /// Returns `None` if the strategy is `SessionIdStrategy::None` or if
33    /// the event doesn't support session-based ordering.
34    pub fn generate_session_id(&self, envelope: &EventEnvelope) -> Option<String> {
35        match &self.strategy {
36            SessionIdStrategy::None => None,
37            SessionIdStrategy::Entity => {
38                // Generate entity-based session ID
39                if let Some(ref id) = envelope.entity_id {
40                    match envelope.entity_type {
41                        EntityType::PullRequest => {
42                            Some(format!("pr-{}-{}", envelope.repository.full_name, id))
43                        }
44                        EntityType::Issue => {
45                            Some(format!("issue-{}-{}", envelope.repository.full_name, id))
46                        }
47                        EntityType::Branch => {
48                            Some(format!("branch-{}-{}", envelope.repository.full_name, id))
49                        }
50                        EntityType::CheckRun => Some(format!(
51                            "check-run-{}-{}",
52                            envelope.repository.full_name, id
53                        )),
54                        EntityType::CheckSuite => Some(format!(
55                            "check-suite-{}-{}",
56                            envelope.repository.full_name, id
57                        )),
58                        EntityType::Release => {
59                            Some(format!("release-{}-{}", envelope.repository.full_name, id))
60                        }
61                        EntityType::Deployment => Some(format!(
62                            "deployment-{}-{}",
63                            envelope.repository.full_name, id
64                        )),
65                        _ => None,
66                    }
67                } else {
68                    None
69                }
70            }
71            SessionIdStrategy::Repository => {
72                // Generate repository-based session ID
73                Some(format!("repo-{}", envelope.repository.full_name))
74            }
75            SessionIdStrategy::Custom(f) => {
76                // Use custom function
77                f(envelope)
78            }
79        }
80    }
81
82    /// Extract an ordering key from an event envelope.
83    ///
84    /// The ordering key is used by queue systems to ensure events with
85    /// the same key are processed in order.
86    pub fn extract_ordering_key(&self, envelope: &EventEnvelope) -> Option<String> {
87        // Ordering key is the same as session ID for this implementation
88        self.generate_session_id(envelope)
89    }
90
91    /// Get an entity-based session strategy.
92    ///
93    /// Creates session IDs in the format: `{entity_type}-{repo}-{entity_id}`
94    /// For example: "pr-owner/repo-123" or "issue-owner/repo-456"
95    pub fn entity_session_strategy() -> SessionIdStrategy {
96        SessionIdStrategy::Custom(
97            |envelope| match (&envelope.entity_type, &envelope.entity_id) {
98                (EntityType::PullRequest, Some(id)) => {
99                    Some(format!("pr-{}-{}", envelope.repository.full_name, id))
100                }
101                (EntityType::Issue, Some(id)) => {
102                    Some(format!("issue-{}-{}", envelope.repository.full_name, id))
103                }
104                (EntityType::Branch, Some(id)) => {
105                    Some(format!("branch-{}-{}", envelope.repository.full_name, id))
106                }
107                _ => None,
108            },
109        )
110    }
111
112    /// Get a repository-based session strategy.
113    ///
114    /// All events for a repository share the same session ID.
115    /// Format: `repo-{owner}/{name}`
116    pub fn repository_session_strategy() -> SessionIdStrategy {
117        SessionIdStrategy::Custom(|envelope| {
118            Some(format!("repo-{}", envelope.repository.full_name))
119        })
120    }
121}
122
123#[cfg(test)]
124#[path = "session_tests.rs"]
125mod tests;