Skip to content

Commit e2bdfcd

Browse files
committed
feat: enhance documentation and add comprehensive module docs
- Add detailed documentation for all core modules including cleanup, config, error handling - Expand README with installation guide, quick start, and advanced usage examples - Add performance benchmarks and development environment setup instructions - Include comprehensive telemetry events and error handling documentation - Add semantic versioning compatibility and contribution guidelines
1 parent 4954b46 commit e2bdfcd

File tree

11 files changed

+1069
-33
lines changed

11 files changed

+1069
-33
lines changed

CLAUDE.md

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ This is Phoenix.SessionProcess, an Elixir library that creates a process for eac
1919
### Testing
2020
The test suite uses ExUnit. Tests are located in the `test/` directory. The test helper starts the supervisor automatically.
2121

22+
### Development Environment
23+
The project uses `devenv` for development environment setup with Nix. Key configuration:
24+
- Uses Elixir/BEAM 27
25+
- Runs `hello` script on shell entry for greeting
26+
- Includes git, figlet, and lolcat tools
27+
28+
### Benchmarking
29+
Performance testing available via:
30+
- `mix run bench/simple_bench.exs` - Quick benchmark (5-10 seconds)
31+
- `mix run bench/session_benchmark.exs` - Comprehensive benchmark (30-60 seconds)
32+
33+
Expected performance:
34+
- Session Creation: 10,000+ sessions/sec
35+
- Memory Usage: ~10KB per session
36+
- Registry Lookups: 100,000+ lookups/sec
37+
2238
## Architecture
2339

2440
### Core Components
@@ -59,15 +75,42 @@ The test suite uses ExUnit. Tests are located in the `test/` directory. The test
5975

6076
The library uses application configuration:
6177
```elixir
62-
config :phoenix_session_process, session_process: MySessionProcess
78+
config :phoenix_session_process,
79+
session_process: MySessionProcess, # Default session module
80+
max_sessions: 10_000, # Maximum concurrent sessions
81+
session_ttl: 3_600_000, # Session TTL in milliseconds (1 hour)
82+
rate_limit: 100 # Sessions per minute limit
6383
```
6484

65-
This sets the default module to use when starting session processes without specifying a module.
85+
Configuration options:
86+
- `session_process`: Default module for session processes (defaults to `Phoenix.SessionProcess.DefaultSessionProcess`)
87+
- `max_sessions`: Maximum concurrent sessions (defaults to 10,000)
88+
- `session_ttl`: Session TTL in milliseconds (defaults to 1 hour)
89+
- `rate_limit`: Sessions per minute limit (defaults to 100)
6690

6791
## Usage in Phoenix Applications
6892

6993
1. Add supervisor to application supervision tree
7094
2. Add SessionId plug after fetch_session
7195
3. Define custom session process modules using the provided macros
7296
4. Start processes with session IDs
73-
5. Communicate using call/cast operations
97+
5. Communicate using call/cast operations
98+
99+
## Telemetry and Error Handling
100+
101+
### Telemetry Events
102+
The library emits comprehensive telemetry events for monitoring:
103+
- `[:phoenix, :session_process, :start]` - Session starts
104+
- `[:phoenix, :session_process, :stop]` - Session stops
105+
- `[:phoenix, :session_process, :call]` - Call operations
106+
- `[:phoenix, :session_process, :cast]` - Cast operations
107+
- `[:phoenix, :session_process, :cleanup]` - Session cleanup
108+
109+
### Error Types
110+
Common error responses:
111+
- `{:error, {:invalid_session_id, session_id}}` - Invalid session ID format
112+
- `{:error, {:session_limit_reached, max_sessions}}` - Maximum sessions exceeded
113+
- `{:error, {:session_not_found, session_id}}` - Session doesn't exist
114+
- `{:error, {:timeout, timeout}}` - Operation timed out
115+
116+
Use `Phoenix.SessionProcess.Error.message/1` for human-readable error messages.

README.md

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
# Phoenix.SessionProcess
22

3-
Create a process for each user session, all user requests go through this process. This provides session isolation, state management, and automatic cleanup with TTL support.
3+
[![Hex Version](https://img.shields.io/hexpm/v/phoenix_session_process.svg)](https://hex.pm/packages/phoenix_session_process)
4+
[![Hex Docs](https://img.shields.io/badge/docs-hexpm-blue.svg)](https://hexdocs.pm/phoenix_session_process/)
5+
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
46

5-
* [Github Repo](https://github.com/gsmlg-dev/phoenix_session_process)
7+
A powerful Phoenix library that creates a dedicated process for each user session. All user requests go through their dedicated session process, providing complete session isolation, robust state management, and automatic cleanup with TTL support.
8+
9+
## Why Phoenix.SessionProcess?
10+
11+
Traditional session management stores session data in external stores (Redis, database) or relies on plug-based state. **Phoenix.SessionProcess** takes a different approach by giving each user their own GenServer process, enabling:
12+
13+
- **Real-time session state** without external dependencies
14+
- **Perfect session isolation** - no shared state between users
15+
- **Built-in LiveView integration** for reactive UIs
16+
- **Automatic memory management** with configurable TTL
17+
- **Enterprise-grade performance** - 10,000+ sessions/second
18+
- **Zero external dependencies** beyond core Phoenix/OTP
619

720
## Features
821

922
- **Session Isolation**: Each user session runs in its own GenServer process
10-
- **Automatic Cleanup**: TTL-based automatic session cleanup
11-
- **Configuration Management**: Configurable TTL, session limits, and rate limiting
23+
- **Automatic Cleanup**: TTL-based automatic session cleanup and memory management
1224
- **LiveView Integration**: Built-in support for monitoring LiveView processes
25+
- **High Performance**: Optimized for 10,000+ concurrent sessions
26+
- **Configuration Management**: Configurable TTL, session limits, and rate limiting
1327
- **Extensible**: Custom session process modules with full GenServer support
14-
- **Validation**: Session ID validation and concurrent session limits
28+
- **Comprehensive Monitoring**: Built-in telemetry and performance metrics
29+
- **Error Handling**: Detailed error reporting and human-readable messages
1530

1631
## Installation
1732

@@ -25,6 +40,12 @@ def deps do
2540
end
2641
```
2742

43+
### Requirements
44+
45+
- Elixir 1.14+
46+
- Erlang/OTP 24+
47+
- Phoenix 1.6+ (recommended)
48+
2849
## Quick Start
2950

3051
### 1. Add to Supervision Tree
@@ -197,19 +218,71 @@ sessions = Phoenix.SessionProcess.list_session()
197218

198219
### Session Process Helpers
199220

200-
Inside your session process, use:
221+
Access session information from within your process:
201222

202223
```elixir
203224
defmodule MyApp.SessionProcess do
204225
use Phoenix.SessionProcess, :process
205226

206-
def get_session_id() do
207-
# Returns the session ID for this process
227+
@impl true
228+
def init(_init_arg) do
229+
# Get the current session ID
230+
session_id = get_session_id()
231+
{:ok, %{session_id: session_id, data: %{}}}
232+
end
233+
234+
def get_current_session_id() do
208235
get_session_id()
209236
end
210237
end
211238
```
212239

240+
### Advanced Usage
241+
242+
#### Rate Limiting
243+
The library includes built-in rate limiting to prevent session abuse:
244+
245+
```elixir
246+
# Configure rate limiting (100 sessions per minute by default)
247+
config :phoenix_session_process,
248+
rate_limit: 200, # 200 sessions per minute
249+
max_sessions: 20_000 # Maximum concurrent sessions
250+
```
251+
252+
#### Custom Session State
253+
Store complex data structures and implement custom logic:
254+
255+
```elixir
256+
defmodule MyApp.ComplexSessionProcess do
257+
use Phoenix.SessionProcess, :process
258+
259+
@impl true
260+
def init(_init_arg) do
261+
{:ok, %{
262+
user: nil,
263+
shopping_cart: [],
264+
preferences: %{},
265+
activity_log: []
266+
}}
267+
end
268+
269+
@impl true
270+
def handle_cast({:add_to_cart, item}, state) do
271+
new_cart = [item | state.shopping_cart]
272+
new_state = %{state | shopping_cart: new_cart}
273+
{:noreply, new_state}
274+
end
275+
276+
@impl true
277+
def handle_call(:get_cart_total, _from, state) do
278+
total = state.shopping_cart
279+
|> Enum.map(& &1.price)
280+
|> Enum.sum()
281+
{:reply, total, state}
282+
end
283+
end
284+
```
285+
213286
## Configuration Options
214287

215288
| Option | Default | Description |
@@ -332,6 +405,33 @@ mix run bench/session_benchmark.exs
332405

333406
See `bench/README.md` for detailed benchmarking guide and customization options.
334407

408+
## Contributing
409+
410+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
411+
412+
### Development Setup
413+
414+
1. Fork the repository
415+
2. Install dependencies: `mix deps.get`
416+
3. Run tests: `mix test`
417+
4. Run benchmarks: `mix run bench/simple_bench.exs`
418+
419+
The project uses `devenv` for development environment management. After installation, run `devenv shell` to enter the development environment.
420+
421+
## Changelog
422+
423+
See [CHANGELOG.md](CHANGELOG.md) for release notes and version history.
424+
335425
## License
336426

337-
[MIT License](LICENSE)
427+
[MIT License](LICENSE)
428+
429+
## Credits
430+
431+
Created by [Jonathan Gao](https://github.com/gsmlg-dev)
432+
433+
## Related Projects
434+
435+
- [Phoenix LiveView](https://hex.pm/packages/phoenix_live_view) - Real-time user experiences
436+
- [Phoenix PubSub](https://hex.pm/packages/phoenix_pubsub) - Distributed PubSub
437+
- [Phoenix Channels](https://hexdocs.pm/phoenix/channels.html) - Real-time communication

lib/phoenix/session_process.ex

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,32 @@ defmodule Phoenix.SessionProcess do
115115
end
116116

117117
@doc """
118-
Get session information including count and modules.
118+
Returns all active sessions as a list of `{session_id, pid}` tuples.
119+
120+
## Examples
121+
122+
iex> sessions = Phoenix.SessionProcess.list_session()
123+
iex> is_list(sessions)
124+
true
125+
iex> [{session_id, pid}] = sessions
126+
"""
127+
128+
@doc """
129+
Returns session statistics including total count and modules in use.
130+
131+
## Examples
132+
133+
iex> info = Phoenix.SessionProcess.session_info()
134+
iex> is_map(info)
135+
true
136+
iex> Map.has_key?(info, :count)
137+
true
138+
iex> Map.has_key?(info, :modules)
139+
true
140+
141+
## Returns
142+
143+
- `%{count: integer(), modules: list(module())}` - A map containing the total number of active sessions and a list of unique session process modules.
119144
"""
120145
@spec session_info() :: %{count: integer(), modules: list(module())}
121146
def session_info() do
@@ -138,7 +163,23 @@ defmodule Phoenix.SessionProcess do
138163
end
139164

140165
@doc """
141-
Get all session IDs for a specific module.
166+
Returns all session IDs for sessions managed by a specific module.
167+
168+
## Examples
169+
170+
iex> sessions = Phoenix.SessionProcess.list_sessions_by_module(MyApp.SessionProcess)
171+
iex> is_list(sessions)
172+
true
173+
iex> Enum.all?(sessions, &is_binary/1)
174+
true
175+
176+
## Parameters
177+
178+
- `module` - The session process module to filter by
179+
180+
## Returns
181+
182+
- `[binary()]` - List of session IDs managed by the specified module
142183
"""
143184
@spec list_sessions_by_module(module()) :: [binary()]
144185
def list_sessions_by_module(module) do
@@ -150,7 +191,28 @@ defmodule Phoenix.SessionProcess do
150191
end
151192

152193
@doc """
153-
Check if a session exists and return its PID if it does.
194+
Finds a session by its ID and returns its PID if it exists.
195+
196+
This is different from `started?/1` in that it returns the actual PID
197+
of the session process, which can be used for direct process operations.
198+
199+
## Examples
200+
201+
iex> {:ok, pid} = Phoenix.SessionProcess.find_session("session_123")
202+
iex> is_pid(pid)
203+
true
204+
205+
iex> {:error, :not_found} = Phoenix.SessionProcess.find_session("nonexistent")
206+
iex> {:error, :not_found}
207+
208+
## Parameters
209+
210+
- `session_id` - The session ID to look up
211+
212+
## Returns
213+
214+
- `{:ok, pid()}` - The PID of the session process if found
215+
- `{:error, :not_found}` - If the session doesn't exist
154216
"""
155217
@spec find_session(binary()) :: {:ok, pid()} | {:error, :not_found}
156218
def find_session(session_id) do
@@ -161,7 +223,28 @@ defmodule Phoenix.SessionProcess do
161223
end
162224

163225
@doc """
164-
Get session statistics including process count and memory usage.
226+
Returns detailed session statistics including process count and memory usage.
227+
228+
Useful for monitoring and debugging session process performance.
229+
230+
## Examples
231+
232+
iex> stats = Phoenix.SessionProcess.session_stats()
233+
iex> is_map(stats)
234+
true
235+
iex> Map.has_key?(stats, :total_sessions)
236+
true
237+
iex> Map.has_key?(stats, :memory_usage)
238+
true
239+
iex> Map.has_key?(stats, :avg_memory_per_session)
240+
true
241+
242+
## Returns
243+
244+
- `%{total_sessions: integer(), memory_usage: integer(), avg_memory_per_session: integer()}` - Session statistics map
245+
- `total_sessions` - Total number of active session processes
246+
- `memory_usage` - Total memory usage in bytes for all session processes
247+
- `avg_memory_per_session` - Average memory usage per session in bytes
165248
"""
166249
@spec session_stats() :: %{
167250
total_sessions: integer(),

0 commit comments

Comments
 (0)