Module: Lich::Common::SessionsSettings

Defined in:
documented/common/settings/sessions_settings.rb

Overview

Lightweight session summary facade for reporting consumers. This module is intentionally reporting-focused and does not enforce process policy.

Constant Summary collapse

FEATURE_FLAG =
:session_summary_store_and_reporting
HEARTBEAT_INTERVAL_SECONDS =
90
STALE_THRESHOLD_SECONDS =
360
IDLE_OVER_30M_SECONDS =
1800
ADAPTER_MUTEX =

Synchronizes lazy initialization of the session database adapter to prevent duplicate adapter creation under concurrent access during startup and reporting.

See Also:

Mutex.new

Class Method Summary collapse

Class Method Details

.adapterLich::Common::SessionDatabaseAdapter

Returns the row-oriented session adapter. Uses synchronized lazy initialization to avoid duplicate adapter creation under concurrent access during startup/reporting.



38
39
40
41
42
43
44
# File 'documented/common/settings/sessions_settings.rb', line 38

def self.adapter
  return @adapter if @adapter

  ADAPTER_MUTEX.synchronize do
    @adapter ||= SessionDatabaseAdapter.new(db: Lich.db)
  end
end

.enabled?Boolean

Indicates whether session summary tracking/reporting is enabled.

The feature flag infrastructure is introduced in a separate prerequisite change. Until that dependency is present, this feature remains safely off.

Returns:

  • (Boolean)


27
28
29
30
31
# File 'documented/common/settings/sessions_settings.rb', line 27

def self.enabled?
  return false unless defined?(Lich::Common::FeatureFlags)

  Lich::Common::FeatureFlags.enabled?(FEATURE_FLAG)
end

.heartbeat(pid:, state: nil, hidden: nil, session_name: nil, role: nil, frontend: nil, game_code: nil, last_utilization_at: nil) ⇒ void

This method returns an undefined value.

Updates heartbeat and runtime fields for a tracked session.

Parameters:

  • pid (Integer)
  • state (String, nil) (defaults to: nil)
  • hidden (Boolean, nil) (defaults to: nil)
  • session_name (String, nil) (defaults to: nil)
  • role (String, nil) (defaults to: nil)
  • frontend (String, nil) (defaults to: nil)
  • game_code (String, nil) (defaults to: nil)
  • last_utilization_at (Integer, nil) (defaults to: nil)


78
79
80
81
82
83
84
85
86
# File 'documented/common/settings/sessions_settings.rb', line 78

def self.heartbeat(pid:, state: nil, hidden: nil, session_name: nil, role: nil, frontend: nil, game_code: nil, last_utilization_at: nil)
  return unless enabled?

  heartbeat_admitted(
    pid: pid, state: state, hidden: hidden, session_name: session_name,
    role: role, frontend: frontend, game_code: game_code,
    last_utilization_at: last_utilization_at
  )
end

.register_session(pid:, session_name:, role:, state:, frontend: nil, game_code: nil, hidden: false, metadata_json: nil) ⇒ void

This method returns an undefined value.

Registers a process as a tracked session row.

Parameters:

  • pid (Integer)
  • session_name (String)
  • role (String)
  • state (String)
  • frontend (String, nil) (defaults to: nil)
  • game_code (String, nil) (defaults to: nil)
  • hidden (Boolean) (defaults to: false)
  • metadata_json (String, nil) (defaults to: nil)


57
58
59
60
61
62
63
64
65
# File 'documented/common/settings/sessions_settings.rb', line 57

def self.register_session(pid:, session_name:, role:, state:, frontend: nil, game_code: nil, hidden: false, metadata_json: nil)
  return unless enabled?

  register_session_admitted(
    pid: pid, session_name: session_name, role: role, state: state,
    frontend: frontend, game_code: game_code, hidden: hidden,
    metadata_json: 
  )
end

.snapshotHash

Builds a normalized reporting snapshot from tracked session rows.

Returns:

  • (Hash)

    deterministic schema consumed by reporting callers



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'documented/common/settings/sessions_settings.rb', line 101

def self.snapshot
  return disabled_snapshot unless enabled?

  rows = adapter.active_sessions
  now = Time.now.to_i
  sessions = rows.map do |row|
    inactive = row['state'] == 'exited'
    if inactive
      os_seen = row['os_seen']
      os_name = row['os_name']
    else
      # Reporting uses authoritative live OS presence, but does not
      # persist those observations back into storage.
      live_presence = os_presence(pid: row['pid'], session_name: row['session_name'], now: now)
      os_seen = live_presence[:os_seen]
      os_name = live_presence[:os_name]
    end
    heartbeat_is_stale = stale?(row['last_heartbeat_at'], now)
    stale = !inactive && (heartbeat_is_stale || os_seen.to_i == 0)
    marker = inactive ? 'inactive' : (stale ? 'stale' : 'active')
    {
      pid: row['pid'],
      session_name: row['session_name'],
      state: row['state'],
      hidden: row['hidden'].to_i == 1,
      role: row['role'],
      last_heartbeat_at: row['last_heartbeat_at'].to_i,
      heartbeat_age: heartbeat_age(row['last_heartbeat_at'], now),
      stale: stale,
      marker: marker,
      os_seen: os_seen.to_i == 1,
      os_name: os_name.nil? ? nil : (os_name.to_i == 1),
      last_utilization: format_last_utilization(row['last_utilization_at'], now)
    }
  end

  {
    source: 'SessionsSettings',
    total: sessions.length,
    idle_over_30m: sessions.count { |s| !s[:heartbeat_age].nil? && s[:heartbeat_age] > IDLE_OVER_30M_SECONDS },
    stale: sessions.count { |s| s[:stale] },
    running: sessions.count { |s| s[:state] == 'running' },
    sleeping: sessions.count { |s| s[:state] == 'sleeping' },
    hidden: sessions.count { |s| s[:hidden] },
    sessions: sessions
  }
rescue StandardError => e
  disabled_snapshot(error: e.message)
end

.unregister_session(pid:) ⇒ void

This method returns an undefined value.

Marks a tracked session as cleanly exited.

Parameters:

  • pid (Integer)


92
93
94
95
96
# File 'documented/common/settings/sessions_settings.rb', line 92

def self.unregister_session(pid:)
  return unless enabled?

  unregister_session_admitted(pid: pid)
end