github-bot-sdk 0.2.1

A comprehensive Rust SDK for GitHub App integration with authentication, webhooks, and API client
Documentation
//! Session management for ordered event processing.

use super::processor::SessionIdStrategy;
use super::{EntityType, EventEnvelope};

/// Manages session IDs for ordered event processing.
///
/// The session manager provides different strategies for grouping related
/// events to ensure they are processed in order. This is critical for
/// maintaining consistency when handling sequences of related events.
///
/// # Examples
///
/// ```rust
/// use github_bot_sdk::events::{SessionManager, SessionIdStrategy};
///
/// let manager = SessionManager::new(SessionIdStrategy::Entity);
/// // Use with event processing...
/// ```
pub struct SessionManager {
    strategy: SessionIdStrategy,
}

impl SessionManager {
    /// Create a new session manager with the given strategy.
    pub fn new(strategy: SessionIdStrategy) -> Self {
        Self { strategy }
    }

    /// Generate a session ID for an event envelope.
    ///
    /// Returns `None` if the strategy is `SessionIdStrategy::None` or if
    /// the event doesn't support session-based ordering.
    pub fn generate_session_id(&self, envelope: &EventEnvelope) -> Option<String> {
        match &self.strategy {
            SessionIdStrategy::None => None,
            SessionIdStrategy::Entity => {
                // Generate entity-based session ID
                if let Some(ref id) = envelope.entity_id {
                    match envelope.entity_type {
                        EntityType::PullRequest => {
                            Some(format!("pr-{}-{}", envelope.repository.full_name, id))
                        }
                        EntityType::Issue => {
                            Some(format!("issue-{}-{}", envelope.repository.full_name, id))
                        }
                        EntityType::Branch => {
                            Some(format!("branch-{}-{}", envelope.repository.full_name, id))
                        }
                        EntityType::CheckRun => Some(format!(
                            "check-run-{}-{}",
                            envelope.repository.full_name, id
                        )),
                        EntityType::CheckSuite => Some(format!(
                            "check-suite-{}-{}",
                            envelope.repository.full_name, id
                        )),
                        EntityType::Release => {
                            Some(format!("release-{}-{}", envelope.repository.full_name, id))
                        }
                        EntityType::Deployment => Some(format!(
                            "deployment-{}-{}",
                            envelope.repository.full_name, id
                        )),
                        _ => None,
                    }
                } else {
                    None
                }
            }
            SessionIdStrategy::Repository => {
                // Generate repository-based session ID
                Some(format!("repo-{}", envelope.repository.full_name))
            }
            SessionIdStrategy::Custom(f) => {
                // Use custom function
                f(envelope)
            }
        }
    }

    /// Extract an ordering key from an event envelope.
    ///
    /// The ordering key is used by queue systems to ensure events with
    /// the same key are processed in order.
    pub fn extract_ordering_key(&self, envelope: &EventEnvelope) -> Option<String> {
        // Ordering key is the same as session ID for this implementation
        self.generate_session_id(envelope)
    }

    /// Get an entity-based session strategy.
    ///
    /// Creates session IDs in the format: `{entity_type}-{repo}-{entity_id}`
    /// For example: "pr-owner/repo-123" or "issue-owner/repo-456"
    pub fn entity_session_strategy() -> SessionIdStrategy {
        SessionIdStrategy::Custom(
            |envelope| match (&envelope.entity_type, &envelope.entity_id) {
                (EntityType::PullRequest, Some(id)) => {
                    Some(format!("pr-{}-{}", envelope.repository.full_name, id))
                }
                (EntityType::Issue, Some(id)) => {
                    Some(format!("issue-{}-{}", envelope.repository.full_name, id))
                }
                (EntityType::Branch, Some(id)) => {
                    Some(format!("branch-{}-{}", envelope.repository.full_name, id))
                }
                _ => None,
            },
        )
    }

    /// Get a repository-based session strategy.
    ///
    /// All events for a repository share the same session ID.
    /// Format: `repo-{owner}/{name}`
    pub fn repository_session_strategy() -> SessionIdStrategy {
        SessionIdStrategy::Custom(|envelope| {
            Some(format!("repo-{}", envelope.repository.full_name))
        })
    }
}

#[cfg(test)]
#[path = "session_tests.rs"]
mod tests;