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;