Class: Woods::SessionTracer::RedisStore

Inherits:
Store
  • Object
show all
Defined in:
lib/woods/session_tracer/redis_store.rb

Overview

Redis-backed session store using Lists.

Each session is stored as a Redis List keyed ‘woods:session:id`. RPUSH per request for append-only ordering. Native TTL for automatic cleanup.

Requires the ‘redis` gem at runtime.

Examples:

store = RedisStore.new(redis: Redis.new, ttl: 3600)
store.record("abc123", { controller: "OrdersController", action: "create" })

Constant Summary collapse

KEY_PREFIX =
'woods:session:'
SESSIONS_KEY =
'woods:sessions'

Instance Method Summary collapse

Constructor Details

#initialize(redis:, ttl: nil) ⇒ RedisStore

Returns a new instance of RedisStore.

Parameters:

  • redis (Redis)

    A Redis client instance

  • ttl (Integer, nil) (defaults to: nil)

    Time-to-live in seconds for session keys (nil = no expiry)



25
26
27
28
29
30
31
32
33
# File 'lib/woods/session_tracer/redis_store.rb', line 25

def initialize(redis:, ttl: nil)
  super()
  unless defined?(::Redis)
    raise SessionTracerError, 'The redis gem is required for RedisStore. Add `gem "redis"` to your Gemfile.'
  end

  @redis = redis
  @ttl = ttl
end

Instance Method Details

#clear(session_id) ⇒ void

This method returns an undefined value.

Remove all data for a single session.

Parameters:

  • session_id (String)

    The session identifier



83
84
85
86
# File 'lib/woods/session_tracer/redis_store.rb', line 83

def clear(session_id)
  @redis.del(session_key(session_id))
  @redis.srem(SESSIONS_KEY, session_id)
end

#clear_allvoid

This method returns an undefined value.

Remove all session data.



91
92
93
94
95
# File 'lib/woods/session_tracer/redis_store.rb', line 91

def clear_all
  all_ids = @redis.smembers(SESSIONS_KEY)
  all_ids.each { |id| @redis.del(session_key(id)) }
  @redis.del(SESSIONS_KEY)
end

#read(session_id) ⇒ Array<Hash>

Read all request records for a session.

Parameters:

  • session_id (String)

    The session identifier

Returns:

  • (Array<Hash>)

    Request records, oldest first



51
52
53
54
55
56
57
58
# File 'lib/woods/session_tracer/redis_store.rb', line 51

def read(session_id)
  key = session_key(session_id)
  @redis.lrange(key, 0, -1).filter_map do |json|
    JSON.parse(json)
  rescue JSON::ParserError
    nil
  end
end

#record(session_id, request_data) ⇒ void

This method returns an undefined value.

Append a request record to a session’s Redis List.

Parameters:

  • session_id (String)

    The session identifier

  • request_data (Hash)

    Request metadata to store



40
41
42
43
44
45
# File 'lib/woods/session_tracer/redis_store.rb', line 40

def record(session_id, request_data)
  key = session_key(session_id)
  @redis.rpush(key, JSON.generate(request_data))
  @redis.expire(key, @ttl) if @ttl
  @redis.sadd(SESSIONS_KEY, session_id)
end

#sessions(limit: 20) ⇒ Array<Hash>

List recent session summaries.

Parameters:

  • limit (Integer) (defaults to: 20)

    Maximum number of sessions to return

Returns:

  • (Array<Hash>)

    Session summaries



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/woods/session_tracer/redis_store.rb', line 64

def sessions(limit: 20)
  all_ids = @redis.smembers(SESSIONS_KEY)

  # Filter to sessions that still have data (TTL may have expired)
  active = all_ids.select { |id| @redis.exists?(session_key(id)) }

  # Remove expired session IDs from the set
  expired = all_ids - active
  expired.each { |id| @redis.srem(SESSIONS_KEY, id) } if expired.any?

  active.first(limit).map do |session_id|
    session_summary(session_id, read(session_id))
  end
end