Class: Tina4::SessionHandlers::FileHandler
- Inherits:
-
Object
- Object
- Tina4::SessionHandlers::FileHandler
- Defined in:
- lib/tina4/session_handlers/file_handler.rb
Instance Method Summary collapse
- #cleanup ⇒ Object
- #destroy(session_id) ⇒ Object
-
#gc(max_age = nil) ⇒ Object
Garbage-collect expired sessions.
-
#initialize(options = {}) ⇒ FileHandler
constructor
TINA4_SESSION_PATH selects the session directory, with the SAME precedence the other three frameworks use: an explicit option wins, then the environment, then "data/sessions".
- #read(session_id) ⇒ Object
-
#write(session_id, data, ttl = 0) ⇒ Object
Write session data.
Constructor Details
#initialize(options = {}) ⇒ FileHandler
TINA4_SESSION_PATH selects the session directory, with the SAME precedence the other three frameworks use: an explicit option wins, then the environment, then "data/sessions".
Ruby read NO env var here and hard-defaulted to path || TINA4_SESSION_PATH || "data/sessions". Pointing the file
backend at a mounted volume worked in three frameworks and was silently
ignored in the fourth, which is the exact "one env var and nothing else"
promise ADR-0024 makes.
The default stays RELATIVE, exactly as the other three leave it, so all four resolve the same path against the same working directory.
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/tina4/session_handlers/file_handler.rb', line 26 def initialize( = {}) @dir = [:dir] || ENV["TINA4_SESSION_PATH"] || File.join("data", "sessions") # TINA4_SESSION_TTL is the ONE session-lifetime variable, and it must # reach EVERY backend (ADR-0024). This used to be a hard-coded 86400, # so an operator setting a 15-minute session got 24 hours here and got # it right only on memcached - the one handler that read the variable. # 3600 is the default in Python (the master), PHP and Node. @ttl = ([:ttl] || ENV["TINA4_SESSION_TTL"] || 3600).to_i FileUtils.mkdir_p(@dir) end |
Instance Method Details
#cleanup ⇒ Object
82 83 84 |
# File 'lib/tina4/session_handlers/file_handler.rb', line 82 def cleanup sweep end |
#destroy(session_id) ⇒ Object
77 78 79 80 |
# File 'lib/tina4/session_handlers/file_handler.rb', line 77 def destroy(session_id) path = session_path(session_id) File.delete(path) if File.exist?(path) end |
#gc(max_age = nil) ⇒ Object
Garbage-collect expired sessions. Matches the Python interface.
90 91 92 |
# File 'lib/tina4/session_handlers/file_handler.rb', line 90 def gc(max_age = nil) sweep(max_age) end |
#read(session_id) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/tina4/session_handlers/file_handler.rb', line 37 def read(session_id) path = session_path(session_id) return nil unless File.exist?(path) stored = JSON.parse(File.read(path)) if expired?(stored, path) File.delete(path) return nil end unwrap(stored) rescue JSON::ParserError nil end |
#write(session_id, data, ttl = 0) ⇒ Object
Write session data.
The ttl is consumed HERE, at write time, and baked into an ABSOLUTE deadline stored beside the payload, so nothing at read time needs to know what the ttl was. That is what makes a per-call ttl durable: a reader with a different ttl can no longer judge someone else's record.
A ttl of 0 (or negative) means NEVER EXPIRES, matching the Python master,
Node, and every mainstream implementation measured. It previously fell
through to the mtime comparison, where mtime + 0 < Time.now made ttl: 0
mean "expire immediately" - the opposite meaning, and the only backend in
any of the four frameworks that read it that way.
68 69 70 71 72 73 74 75 |
# File 'lib/tina4/session_handlers/file_handler.rb', line 68 def write(session_id, data, ttl = 0) effective_ttl = ttl.to_i.positive? ? ttl.to_i : @ttl expires_at = effective_ttl.positive? ? Time.now.to_f + effective_ttl : 0.0 File.write( session_path(session_id), JSON.generate({ "_data" => data, "_expires" => expires_at }) ) end |