Module: Sentiero::Store::SessionStore

Included in:
Sentiero::Store
Defined in:
lib/sentiero/store/session_store.rb

Overview

The session-replay store contract: recording windows of rrweb events and reading them back as sessions.

Window-level methods take a Sentiero::WindowRef; session-level methods take a bare session_id.

Instance Method Summary collapse

Instance Method Details

#delete_session(session_id) ⇒ Object

Raises:

  • (NoMethodError)


27
28
29
# File 'lib/sentiero/store/session_store.rb', line 27

def delete_session(session_id)
  raise NoMethodError, "#{self.class}#delete_session not implemented"
end

#delete_window(ref) ⇒ Object

Raises:

  • (NoMethodError)


31
32
33
# File 'lib/sentiero/store/session_store.rb', line 31

def delete_window(ref)
  raise NoMethodError, "#{self.class}#delete_window not implemented"
end

#each_session_events(limit: nil, since: nil, until_time: nil) ⇒ Object

Yields [session_summary_hash, window_id, events_array] per window, newest sessions first, capped at limit. Built from list_sessions/get_session/ get_events so every backend gets it free; stores may override.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/sentiero/store/session_store.rb', line 43

def each_session_events(limit: nil, since: nil, until_time: nil)
  return enum_for(:each_session_events, limit: limit, since: since, until_time: until_time) unless block_given?

  cap = limit || limits.analytics_max_scan_sessions
  sessions = list_sessions(limit: cap, since: since, until_time: until_time)

  sessions.each do |summary|
    session = get_session(summary[:session_id])
    next unless session

    windows = session[:windows] || []
    windows.each do |window|
      window_id = window[:window_id]
      events = get_events(WindowRef.new(summary[:session_id], window_id))
      yield summary, window_id, events
    end
  end
end

#get_events(ref, after: nil, limit: nil) ⇒ Object

Raises:

  • (NoMethodError)


23
24
25
# File 'lib/sentiero/store/session_store.rb', line 23

def get_events(ref, after: nil, limit: nil)
  raise NoMethodError, "#{self.class}#get_events not implemented"
end

#get_session(session_id) ⇒ Object

Raises:

  • (NoMethodError)


19
20
21
# File 'lib/sentiero/store/session_store.rb', line 19

def get_session(session_id)
  raise NoMethodError, "#{self.class}#get_session not implemented"
end

#list_sessions(limit:, offset: 0, since: nil, until_time: nil, sort_by: nil, search: nil) ⇒ Object

Raises:

  • (NoMethodError)


15
16
17
# File 'lib/sentiero/store/session_store.rb', line 15

def list_sessions(limit:, offset: 0, since: nil, until_time: nil, sort_by: nil, search: nil)
  raise NoMethodError, "#{self.class}#list_sessions not implemented"
end

#purge_older_than(seconds) ⇒ Object

Deletes every session whose updated_at is older than seconds ago, returning the count. Built from list_sessions + delete_session so every backend gets it free; stores may override with a direct query.

list_sessions is newest-first, so stale sessions are the last ones reached: we page through the whole store by advancing an offset (not just re-reading the first batch) and delete only after the full scan, so deletions don't shift the pages we're still walking.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/sentiero/store/session_store.rb', line 70

def purge_older_than(seconds)
  cutoff = Time.now.to_f - seconds
  batch_size = limits.analytics_max_scan_sessions
  stale = []
  offset = 0

  loop do
    summaries = list_sessions(limit: batch_size, offset: offset)
    break if summaries.empty?

    stale.concat(
      summaries
        .select { |summary| summary[:updated_at] < cutoff }
        .map { |summary| summary[:session_id] }
    )
    break if summaries.size < batch_size

    offset += batch_size
  end

  stale.each { |session_id| delete_session(session_id) }
  stale.size
end

#save_events(ref, events) ⇒ Object

Raises:

  • (NoMethodError)


11
12
13
# File 'lib/sentiero/store/session_store.rb', line 11

def save_events(ref, events)
  raise NoMethodError, "#{self.class}#save_events not implemented"
end

#save_metadata(session_id, metadata) ⇒ Object

Optional; default is a no-op so custom stores keep working without it.



36
37
38
# File 'lib/sentiero/store/session_store.rb', line 36

def (session_id, )
  nil
end