Packages

Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.

Current section

Files

Jump to
raxol lib raxol web session storage.ex
Raw

lib/raxol/web/session/storage.ex

defmodule Raxol.Web.Session.Storage do
@moduledoc """
Handles session storage and retrieval for Raxol applications.
This module provides persistent storage for session data using ETS tables
and optional database storage for long-term persistence.
"""
alias Raxol.Repo
alias Raxol.Web.Session.Session
# ETS table name for session storage
@table_name :session_storage
@doc """
Initialize the session storage system.
"""
def init do
# Create ETS table for session storage
_ = :ets.new(@table_name, [:named_table, :set, :public])
:ok
end
@doc """
Store a session in the storage system.
"""
def store(session) do
# Store in ETS for fast access
:ets.insert(@table_name, {session.id, session})
# Store in database for persistence
case Repo.get(Session, session.id) do
nil ->
# Create new session
%Session{}
|> Session.changeset(Map.from_struct(session))
|> Repo.insert()
existing ->
# Update existing session
existing
|> Session.changeset(Map.from_struct(session))
|> Repo.update()
end
end
@doc """
Retrieve a session from storage.
"""
def get(session_id) do
# Try ETS first
case :ets.lookup(@table_name, session_id) do
[{^session_id, session}] ->
{:ok, session}
[] ->
# Try database
case Repo.get(Session, session_id) do
nil -> {:error, :not_found}
session -> {:ok, session}
end
end
end
@doc """
Get all expired sessions.
"""
def get_expired_sessions(timeout) do
# Get current time
now = DateTime.utc_now()
# Get all sessions from ETS
sessions = :ets.tab2list(@table_name)
# Filter expired sessions
Enum.filter(sessions, fn {_id, session} ->
# Check if session is active and last active time is older than timeout
session.status == :active &&
DateTime.diff(now, session.last_active) > div(timeout, 1000)
end)
|> Enum.map(fn {_id, session} -> session end)
end
@doc """
Delete a session from storage.
"""
def delete(session_id) do
# Delete from ETS
:ets.delete(@table_name, session_id)
# Delete from database
case Repo.get(Session, session_id) do
nil -> :ok
session -> Repo.delete(session)
end
end
@doc """
Get all active sessions.
"""
def get_active_sessions do
:ets.tab2list(@table_name)
|> Enum.filter(fn {_id, session} -> session.status == :active end)
|> Enum.map(fn {_id, session} -> session end)
end
end