This repository has been archived by the owner on Dec 25, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
application.rb
89 lines (76 loc) · 2.21 KB
/
application.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
require 'thread'
require 'wee/id_generator'
require 'wee/lru_cache'
module Wee
#
# A Wee::Application manages all Session's of a single application. It
# dispatches the request to the correct handler by examining the request.
#
class Application
def self.for(component_class, session_class=Wee::Session, *component_args)
new { session_class.new(component_class.new(*component_args)) }
end
class SessionCache < Wee::LRUCache
def garbage_collect
delete_if {|id, session| session.dead? }
end
end
#
# Creates a new application. The block, when called, must
# return a new Session instance.
#
# Wee::Application.new { Wee::Session.new(root_component) }
#
def initialize(max_sessions=10_000, &block)
@session_factory = block || raise(ArgumentError)
@session_ids ||= Wee::IdGenerator::Secure.new
@sessions = SessionCache.new(max_sessions)
@mutex = Mutex.new
end
#
# Garbage collect dead sessions
#
def cleanup_sessions
@mutex.synchronize { @sessions.garbage_collect }
end
#
# Handles a web request
#
def call(env)
request = Wee::Request.new(env)
if request.session_id
session = @mutex.synchronize { @sessions.fetch(request.session_id) }
if session and session.alive?
session.call(env)
else
url = request.build_url(:session_id => nil, :page_id => nil)
Wee::RefreshResponse.new("Invalid or expired session", url).finish
end
else
session = new_session()
url = request.build_url(:session_id => session.id, :page_id => nil)
Wee::RedirectResponse.new(url).finish
end
end
protected
def new_session
session = @session_factory.call
session.application = self
insert_session(session)
return session
end
def insert_session(session, retries=3)
retries.times do
@mutex.synchronize {
id = @session_ids.next
if not @sessions.has_key?(id)
@sessions.store(id, session)
session.id = id
return
end
}
end
raise
end
end # class Application
end # module Wee