# Concierge::Sessions - Session Management System **Version:** 0.8.1 Concierge::Sessions is a comprehensive session management system for Perl applications, providing flexible storage backends, sliding window expiration, and application-controlled data storage. Sessions enable applications to track user actions and maintain state across multiple operations. Keep session data in memory for fast access, persist to storage when needed, and maintain continuity between user interactions whether in online services, CLI tools, games, time-billing systems, or any application that needs to track state over time. ## Features - **Application-controlled data storage**: Store any serializable data structure in sessions - **In-memory performance**: Fast access to state and configuration - **Optional persistence**: Session tracks changes, saves when App tells it to - **Single-session enforcement**: Enforces one active session per user - **Sliding window expiration**: Sessions auto-extend when users are active - **Indefinite sessions**: Application-wide sessions that never expire - **Multiple backends**: database (production), file (testing/small user population) - **Modern Perl**: v5.36+ with contemporary best practices - **Service layer pattern**: Non-fatal errors with descriptive messages ## Installation Standard CPAN installation: ```bash cpanm Concierge::Sessions # OR perl Makefile.PL make make test make install ``` ## Requirements - Perl 5.36 or later - DBI (for SQLite backend) - DBD::SQLite (for SQLite backend) - JSON::PP or JSON - Time::HiRes - File::Spec - Test2::V0 (for testing) ## Quick Start ```perl use Concierge::Sessions; # Create session manager my $sessions = Concierge::Sessions->new( backend => 'database', storage_dir => '/var/app/sessions', ); # Create user session my $result = $sessions->new_session( user_id => 'user123', data => { cart => [], preferences => { theme => 'dark' }, }, ); if ($result->{success}) { my $session = $result->{session}; my $session_id = $session->session_id(); # Read session data my $data_result = $session->get_data(); my $data = $data_result->{value}; # Update session data $data->{cart} = ['item1', 'item2']; $session->set_data($data); # Save changes (extends session timeout) $session->save(); } # Retrieve session later my $retrieved = $sessions->get_session($session_id); ``` ## Usage Patterns ### Sliding Window Expiration Sessions automatically extend when `save()` is called: ```perl my $session = $sessions->new_session( user_id => 'user123', session_timeout => 3600, # 1 hour )->{session}; # User activity - save() extends the session $session->save(); # Session now expires 1 hour from now ``` Active users stay logged in; inactive users expire automatically. ### Indefinite Sessions For application-wide state that never expires: ```perl my $app_session = $sessions->new_session( user_id => 'application_main', session_timeout => 'indefinite', data => { metrics => { requests_processed => 0 }, subsystems => { database => 'connected' }, }, )->{session}; # This session never expires $app_session->is_expired(); # Always returns false ``` ### Data Access All data operations work with the entire data field: ```perl # Get entire data structure my $result = $session->get_data(); my $data = $result->{value}; # Modify the data structure $data->{username} = 'alice'; $data->{preferences}{language} = 'en'; $data->{cart} = [@items]; # Replace entire data field (marks session as dirty) $session->set_data($data); # Persist to backend (also extends session timeout) $session->save(); ``` ### Session Lifecycle ```perl # Create my $result = $sessions->new_session(user_id => 'user123'); my $session = $result->{session}; # Check session status if ($session->is_valid()) { # Session is active and not expired } # Retrieve later my $retrieved = $sessions->get_session($session->session_id()); # Delete when done $sessions->delete_session($session->session_id()); ``` ### Backend Selection ```perl # Database backend (production, high performance) my $sessions = Concierge::Sessions->new( backend => 'database', storage_dir => '/var/app/sessions', ); # File backend (testing, human-readable) my $sessions = Concierge::Sessions->new( backend => 'file', storage_dir => '/tmp/sessions', ); ``` ## API Overview ### Concierge::Sessions (Factory) All factory methods return hashrefs with `{success => 1|0, ...}`: ```perl $sessions->new_session(user_id => ..., data => ...) # Returns: {success => 1, session => $session_object} $sessions->get_session($session_id) # Returns: {success => 1, session => $session_object} $sessions->delete_session($session_id) # Returns: {success => 1, message => '...'} $sessions->delete_user_session($user_id) # Returns: {success => 1, deleted_count => 3} $sessions->cleanup_sessions() # Returns: {success => 1, deleted_count => 5} ``` ### Concierge::Sessions::Session (Session Object) ```perl # Data methods $session->get_data() # {success => 1, value => $data} $session->set_data($data) # {success => 1} $session->save() # {success => 1} # Status checks $session->is_valid() # 1 if active and not expired $session->is_active() # 1 if state is 'active' $session->is_expired() # 1 if past expiration time $session->is_dirty() # 1 if unsaved changes exist # Accessors $session->session_id() # Session ID string $session->created_at() # Creation timestamp $session->expires_at() # Expiration timestamp $session->last_updated() # Last update timestamp $session->storage_backend() # Backend class name $session->status() # {state => 'active', dirty => 0} ``` ## Design Principles ### Explicit Persistence No automatic saving on scope exit. You control when data is persisted: ```perl $session->set_data($new_data); # Changes in memory only $session->is_dirty(); # True - changes not saved $session->save(); # Persists to backend $session->is_dirty(); # False - saved ``` ### Single-Session Enforcement Only one active session per user. Creating a new session invalidates old ones: ```perl my $session1 = $sessions->new_session(user_id => 'user123')->{session}; my $session2 = $sessions->new_session(user_id => 'user123')->{session}; # $session1 is now deleted (enforced by backend) ``` ### Service Layer Pattern All methods return consistent result hashrefs. The module only dies/croaks during initialization if the backend cannot be initialized. All other failures are non-fatal: ```perl # Factory methods return hashrefs my $result = $sessions->new_session(user_id => 'user123'); if ($result->{success}) { my $session = $result->{session}; # Use session } else { warn "Failed to create session: " . $result->{message}; } # Session object methods also return hashrefs my $save_result = $session->save(); if ($save_result->{success}) { # Session saved successfully } else { warn "Failed to save session: " . $save_result->{message}; } ``` **Default Session Timeout**: If not specified, sessions timeout after 3600 seconds (1 hour). Use `session_timeout => 'indefinite'` for sessions that never expire. ## Documentation Full API documentation is available in the module POD: ```bash perldoc Concierge::Sessions perldoc Concierge::Sessions::Session ``` ## Testing ```bash # Run all tests prove -lv t/ # Run specific test file prove -lv t/01-sessions-manager.t ``` Test coverage: 75 tests across 4 test files, all passing. ## Examples See the `examples/` directory for usage examples: - `04-indefinite-session.pl` - Application-wide session demonstration ## Performance - **SQLite backend**: 4,000-5,000 operations per second - **File backend**: ~1,000 operations per second Benchmarks performed on typical hardware with default settings. ## License Artistic License 2.0 - See [LICENSE](LICENSE) file for details. This is the same license as Perl itself. ## Author Bruce Van Allen ## See Also - [DBI](https://metacpan.org/pod/DBI) - Database interface - [JSON::PP](https://metacpan.org/pod/JSON::PP) - JSON handling - [Time::HiRes](https://metacpan.org/pod/Time::HiRes) - High resolution time ## Version History ### Version 0.8.1 (Current) - Backend parameter names: 'database' and 'file' (case-insensitive) - Method name updates: delete_user_session, cleanup_sessions - Version alignment across all modules ### Version 0.7.0 - Initial release as Concierge::Sessions - Sliding window session expiration - Indefinite session support - Multiple backend support (database, file) - 75 tests, all passing - Production-ready