mongo_rack 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +4 -4
- data/aa.rb +22 -0
- data/fred.rb +26 -0
- data/lib/mongo_rack.rb +87 -25
- data/spec/mongo_rack_spec.rb +55 -10
- data/spec/session_hash_spec.rb +1 -2
- data/spec/spec_helper.rb +5 -3
- data/tasks/gem.rake +1 -1
- data/tasks/rdoc.rake +3 -2
- metadata +17 -5
data/Rakefile
CHANGED
@@ -15,17 +15,17 @@ require 'mongo_rack'
|
|
15
15
|
task :default => 'spec:run'
|
16
16
|
|
17
17
|
PROJ.name = 'mongo_rack'
|
18
|
+
PROJ.version = "0.0.3"
|
18
19
|
PROJ.authors = 'Fernand Galiana'
|
19
20
|
PROJ.email = 'fernand.galiana@gmail.com'
|
20
21
|
PROJ.url = 'http://github.com/derailed/mongo_rack'
|
21
22
|
PROJ.summary = "Rackable mongoDB based session management"
|
22
|
-
PROJ.version = "0.0.2"
|
23
23
|
PROJ.ruby_opts = %w[-W0]
|
24
24
|
PROJ.readme = 'README.rdoc'
|
25
25
|
PROJ.rcov.opts = ["--sort", "coverage", "-T"]
|
26
26
|
PROJ.spec.opts << '--color'
|
27
27
|
|
28
28
|
# Dependencies
|
29
|
-
depend_on "rack" , ">= 1.0.
|
30
|
-
depend_on "mongo" , ">= 0.18.
|
31
|
-
depend_on "mongo_ext", ">= 0.18.
|
29
|
+
depend_on "rack" , ">= 1.0.1"
|
30
|
+
depend_on "mongo" , ">= 0.18.2"
|
31
|
+
depend_on "mongo_ext", ">= 0.18.2"
|
data/aa.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class Fred
|
6
|
+
attr_accessor :blee, :duh, :zob
|
7
|
+
|
8
|
+
def initialize( blee, duh )
|
9
|
+
@blee = blee
|
10
|
+
@duh = duh
|
11
|
+
@zob = 100
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
f = Fred.new( 10, "Hello" )
|
16
|
+
|
17
|
+
buff = f.to_yaml
|
18
|
+
|
19
|
+
nf = YAML.load( buff )
|
20
|
+
|
21
|
+
puts nf.inspect
|
22
|
+
|
data/fred.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# tnum = 10
|
2
|
+
# r = Array.new(tnum) do
|
3
|
+
# Thread.new do
|
4
|
+
# puts "Making request"
|
5
|
+
# 10
|
6
|
+
# end
|
7
|
+
# end.reverse.map{|t| puts t.inspect;t.join; puts t.value }
|
8
|
+
#
|
9
|
+
# r.each do |res|
|
10
|
+
# puts "Checking request #{res}"
|
11
|
+
# end
|
12
|
+
|
13
|
+
|
14
|
+
a = Array.new( 10 ) do
|
15
|
+
Thread.new( 20 ) do |run|
|
16
|
+
puts "Blee + #{run}"
|
17
|
+
20
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
puts a.inspect
|
22
|
+
|
23
|
+
b = a.reverse.map{ |t| t.join.value }
|
24
|
+
|
25
|
+
puts "Here"
|
26
|
+
puts b.inspect
|
data/lib/mongo_rack.rb
CHANGED
@@ -2,6 +2,8 @@ require 'rack/session/abstract/id'
|
|
2
2
|
require 'mongo'
|
3
3
|
require File.expand_path( File.join( File.dirname(__FILE__), %w[mongo_rack session_hash.rb] ) )
|
4
4
|
require File.expand_path( File.join( File.dirname(__FILE__), %w[core_ext hash.rb] ) )
|
5
|
+
require 'yaml'
|
6
|
+
require 'logger'
|
5
7
|
|
6
8
|
module Rack
|
7
9
|
module Session
|
@@ -19,10 +21,13 @@ module Rack
|
|
19
21
|
# :pool_timeout ::
|
20
22
|
# The connection pool timeout. see mongo-ruby-driver docs for settings.
|
21
23
|
# Defaults to 1 sec.
|
24
|
+
# :logging ::
|
25
|
+
# Set to true to enable logger. Default is false
|
22
26
|
DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \
|
23
27
|
:server => 'localhost:27017/mongo_session/sessions',
|
24
28
|
:pool_size => 1,
|
25
|
-
:pool_timeout => 1.0
|
29
|
+
:pool_timeout => 1.0,
|
30
|
+
:log_level => :fatal
|
26
31
|
|
27
32
|
# Initializes mongo_rack. Pass in options for default override.
|
28
33
|
def initialize(app, options={})
|
@@ -31,13 +36,18 @@ module Rack
|
|
31
36
|
host, port, db_name, cltn_name = parse_server_desc( @default_options[:server] )
|
32
37
|
|
33
38
|
@mutex = Mutex.new
|
34
|
-
@connection = ::Mongo::Connection.new(
|
39
|
+
@connection = ::Mongo::Connection.new(
|
40
|
+
host,
|
41
|
+
port,
|
35
42
|
:pool_size => @default_options[:pool_size],
|
36
43
|
:timeout => @default_options[:pool_timeout] )
|
37
44
|
@db = @connection.db( db_name )
|
38
45
|
@sessions = @db[cltn_name]
|
46
|
+
|
47
|
+
@logger = Logger.new( $stdout )
|
48
|
+
@logger.level = set_log_level( @default_options[:log_level] )
|
39
49
|
end
|
40
|
-
|
50
|
+
|
41
51
|
# Fetch session with optional session id. Retrieve session from mongodb if any
|
42
52
|
def get_session( env, sid )
|
43
53
|
return _get_session( env, sid ) unless env['rack.multithread']
|
@@ -85,35 +95,57 @@ module Rack
|
|
85
95
|
raise "Invalid host:port description" unless server_desc.size == 2
|
86
96
|
return server_desc.first, server_desc.last.to_i, tokens[1], tokens[2]
|
87
97
|
end
|
88
|
-
|
98
|
+
|
99
|
+
# Use YAML to store session objects
|
100
|
+
def serialize( ses )
|
101
|
+
YAML::dump( ses )
|
102
|
+
end
|
103
|
+
|
104
|
+
# Session object stored in YAML
|
105
|
+
def deserialize( buff )
|
106
|
+
YAML::load( buff )
|
107
|
+
end
|
108
|
+
|
89
109
|
# fetch session with optional session id
|
90
110
|
def _get_session(env, sid)
|
111
|
+
logger.debug "Getting session info for #{sid.inspect}"
|
91
112
|
if sid
|
92
113
|
ses_obj = sessions.find_one( { :_id => sid } )
|
93
|
-
|
114
|
+
if ses_obj
|
115
|
+
logger.debug "Found session object on #{sid.inspect}"
|
116
|
+
else
|
117
|
+
logger.debug "Unable to find session object #{sid.inspect}"
|
118
|
+
end
|
119
|
+
session = MongoRack::SessionHash.new( deserialize(ses_obj['data']) ) if ses_obj and fresh?( ses_obj )
|
94
120
|
end
|
95
121
|
|
96
122
|
unless sid and session
|
97
|
-
|
98
|
-
session =
|
123
|
+
logger.warn "Session ID not found - #{sid.inspect} - Creating new session"
|
124
|
+
session = MongoRack::SessionHash.new
|
99
125
|
sid = generate_sid
|
100
|
-
ret = sessions.save( { :_id => sid, :data => session } )
|
126
|
+
ret = sessions.save( { :_id => sid, :data => serialize(session) } )
|
101
127
|
raise "Session collision on '#{sid.inspect}'" unless ret
|
102
128
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
129
|
+
merged = MongoRack::SessionHash.new.merge(session)
|
130
|
+
logger.debug "Setting old session #{merged.inspect}"
|
131
|
+
session.instance_variable_set( '@old', merged )
|
132
|
+
return [sid, session]
|
133
|
+
rescue => boom
|
134
|
+
logger.error "#{self} Hoy! something bad happened loading session data"
|
135
|
+
logger.error $!.inspect
|
136
|
+
boom.backtrace.each{ |l| logger.error l }
|
137
|
+
return [ nil, MongoRack::SessionHash.new ]
|
109
138
|
end
|
110
139
|
|
111
140
|
# update session information with new settings
|
112
141
|
def _set_session(env, sid, new_session, options)
|
142
|
+
logger.debug "Setting session #{new_session.inspect}"
|
113
143
|
ses_obj = sessions.find_one( { :_id => sid } )
|
114
144
|
if ses_obj
|
115
|
-
session
|
145
|
+
logger.debug "Found existing session for -- #{sid.inspect}"
|
146
|
+
session = MongoRack::SessionHash.new( deserialize( ses_obj['data'] ) )
|
116
147
|
else
|
148
|
+
logger.debug "Unable to find session for -- #{sid.inspect}"
|
117
149
|
session = MongoRack::SessionHash.new
|
118
150
|
end
|
119
151
|
|
@@ -124,37 +156,67 @@ module Rack
|
|
124
156
|
sessions.insert( {:_id => sid, :data => {} } )
|
125
157
|
end
|
126
158
|
old_session = new_session.instance_variable_get('@old') || MongoRack::SessionHash.new
|
159
|
+
logger.debug "Setting old session -- #{old_session.inspect}"
|
127
160
|
merged = merge_sessions( sid, old_session, new_session, session )
|
128
161
|
|
129
162
|
expiry = options[:expire_after]
|
130
163
|
expiry = expiry ? Time.now + options[:expire_after] : 0
|
131
164
|
|
132
165
|
# BOZO ! Use upserts here if minor changes ?
|
133
|
-
|
166
|
+
logger.debug "Updating session -- #{merged.inspect}"
|
167
|
+
sessions.save( { :_id => sid, :data => serialize( merged ), :expire => expiry } )
|
134
168
|
return sid
|
135
|
-
rescue => boom
|
136
|
-
|
137
|
-
|
169
|
+
rescue => boom
|
170
|
+
logger.error "#{self} Hoy! Something went wrong. Unable to persist session."
|
171
|
+
logger.error $!.inspect
|
172
|
+
boom.backtrace.each{ |l| logger.error l }
|
138
173
|
return false
|
139
174
|
end
|
140
175
|
|
141
176
|
# merge old, new to current session state
|
142
177
|
def merge_sessions( sid, old_s, new_s, cur={} )
|
143
178
|
unless Hash === old_s and Hash === new_s
|
144
|
-
|
179
|
+
logger.error 'Bad old or new sessions provided.'
|
145
180
|
return cur
|
146
181
|
end
|
147
|
-
|
182
|
+
|
148
183
|
delete = old_s.keys - new_s.keys
|
149
|
-
|
184
|
+
logger.info "//@#{sid}: delete #{delete*','}" if not delete.empty?
|
150
185
|
delete.each{ |k| cur.delete(k) }
|
151
186
|
|
152
|
-
update = new_s.keys.select
|
153
|
-
|
154
|
-
|
187
|
+
update = new_s.keys.select do |k|
|
188
|
+
logger.debug "Update #{k}-#{new_s[k] != old_s[k]}? #{new_s[k].inspect} - #{old_s[k].inspect}";
|
189
|
+
new_s[k] != old_s[k]
|
190
|
+
end
|
155
191
|
|
192
|
+
logger.info "//@#{sid}: update #{update*','}" if not update.empty?
|
193
|
+
update.each{ |k| cur[k] = new_s[k] }
|
156
194
|
cur
|
157
195
|
end
|
196
|
+
|
197
|
+
# Logger handle
|
198
|
+
def logger
|
199
|
+
@logger
|
200
|
+
end
|
201
|
+
|
202
|
+
# Set the log level
|
203
|
+
def set_log_level( level )
|
204
|
+
case level
|
205
|
+
when :fatal
|
206
|
+
Logger::FATAL
|
207
|
+
when :error
|
208
|
+
Logger::ERROR
|
209
|
+
when :warn
|
210
|
+
Logger::WARN
|
211
|
+
when :info
|
212
|
+
Logger::INFO
|
213
|
+
when :debug
|
214
|
+
Logger::DEBUG
|
215
|
+
else
|
216
|
+
Logger::INFO
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
158
220
|
end
|
159
221
|
end
|
160
222
|
end
|
data/spec/mongo_rack_spec.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require File.expand_path(
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[spec_helper]))
|
2
|
+
require 'core_ext/hash'
|
2
3
|
|
3
4
|
describe Rack::Session::Mongo do
|
4
5
|
before :all do
|
5
6
|
@session_key = 'rack.session'
|
6
7
|
@session_match = /#{@session_key}=[0-9a-fA-F]+;/
|
7
|
-
@db_name = '
|
8
|
+
@db_name = 'mongo_rack_test'
|
8
9
|
@cltn_name = 'sessions'
|
9
10
|
|
10
11
|
@con = Mongo::Connection.new
|
@@ -45,9 +46,11 @@ describe Rack::Session::Mongo do
|
|
45
46
|
req = Rack::MockRequest.new( @pool )
|
46
47
|
res = req.get("/", 'rack.multithread' => false )
|
47
48
|
cookie = res["Set-Cookie"]
|
48
|
-
req.get("/", "HTTP_COOKIE" => cookie, 'rack.multithread' => false )
|
49
|
+
res = req.get("/", "HTTP_COOKIE" => cookie, 'rack.multithread' => false )
|
50
|
+
res.body.should == '{"counter"=>2}'
|
49
51
|
mongo_check( res, :counter, 2 )
|
50
|
-
req.get("/", "HTTP_COOKIE" => cookie, 'rack.multithread' => false )
|
52
|
+
res = req.get("/", "HTTP_COOKIE" => cookie, 'rack.multithread' => false )
|
53
|
+
res.body.should == '{"counter"=>3}'
|
51
54
|
mongo_check( res, :counter, 3 )
|
52
55
|
end
|
53
56
|
|
@@ -157,6 +160,7 @@ describe Rack::Session::Mongo do
|
|
157
160
|
res3.body.should == '{"counter"=>4}'
|
158
161
|
end
|
159
162
|
|
163
|
+
# BOZO !! Review...
|
160
164
|
it "multithread: should cleanly merge sessions" do
|
161
165
|
pending do
|
162
166
|
@pool = Rack::Session::Mongo.new( @incrementor, :server => "localhost:27017/#{@db_name}/#{@cltn_name}", :pool_size => 10 )
|
@@ -182,7 +186,7 @@ describe Rack::Session::Mongo do
|
|
182
186
|
drop_counter = proc do |env|
|
183
187
|
env['rack.session'].delete 'counter'
|
184
188
|
env['rack.session']['foo'] = 'bar'
|
185
|
-
[200, {'Content-Type'=>'text/plain'},
|
189
|
+
[200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
|
186
190
|
end
|
187
191
|
tses = Rack::Utils::Context.new @pool, drop_counter
|
188
192
|
treq = Rack::MockRequest.new( tses )
|
@@ -198,11 +202,52 @@ describe Rack::Session::Mongo do
|
|
198
202
|
res.body.should include('"foo"=>"bar"')
|
199
203
|
end
|
200
204
|
|
201
|
-
|
202
|
-
|
203
|
-
session['data']
|
204
|
-
session
|
205
|
+
result = @pool.sessions.find_one( {:_id => sess_id } )
|
206
|
+
result.should_not be_nil
|
207
|
+
session = YAML.load( result['data'] )
|
208
|
+
session.size.should == 1
|
209
|
+
session['counter'].should be_nil
|
210
|
+
session['foo'].should == 'bar'
|
205
211
|
end
|
206
|
-
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "serialization" do
|
216
|
+
before( :all ) do
|
217
|
+
@pool = Rack::Session::Mongo.new( @incrementor, :server => "localhost:27017/#{@db_name}/#{@cltn_name}" )
|
218
|
+
@env = {}
|
219
|
+
@opts = {}
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should store a hash in session correctly" do
|
223
|
+
sid = 10
|
224
|
+
ses = { 'a' => 1, 'b' => 2 }
|
225
|
+
@pool.send(:_set_session, @env, sid, ses, @opts )
|
226
|
+
results = @pool.send(:_get_session, @env, sid )
|
227
|
+
results.last.should == ses
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should store an object in session correctly" do
|
231
|
+
sid = 11
|
232
|
+
fred = Fred.new( 10, "Hello" )
|
233
|
+
ses = { :fred => fred }
|
234
|
+
@pool.send(:_set_session, @env, sid, ses, @opts )
|
235
|
+
results = @pool.send(:_get_session, @env, sid )
|
236
|
+
[:fred, 'fred'].each do |key|
|
237
|
+
results.last[key].blee.should == 10
|
238
|
+
results.last[key].duh.should == "Hello"
|
239
|
+
results.last[key].zob.should == 100
|
240
|
+
end
|
241
|
+
end
|
207
242
|
end
|
243
|
+
|
244
|
+
class Fred
|
245
|
+
attr_accessor :blee, :duh, :zob
|
246
|
+
def initialize( blee, duh )
|
247
|
+
@blee = blee
|
248
|
+
@duh = duh
|
249
|
+
@zob = 100
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
208
253
|
end
|
data/spec/session_hash_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require File.expand_path(
|
2
|
-
require File.expand_path( File.join( File.dirname(__FILE__), %w[.. lib core_ext hash] ) )
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[spec_helper]))
|
3
2
|
|
4
3
|
describe MongoRack::SessionHash do
|
5
4
|
before :all do
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rack'
|
3
3
|
require 'rack/test'
|
4
4
|
require 'rack/response'
|
5
|
+
require 'yaml'
|
5
6
|
|
6
7
|
require File.expand_path( File.join( File.dirname(__FILE__), %w[.. lib mongo_rack] ) )
|
7
8
|
|
@@ -10,9 +11,10 @@ end
|
|
10
11
|
|
11
12
|
def mongo_check( res, key, val )
|
12
13
|
session_id = res['Set-Cookie'].match( /^#{@session_key}=(.*?);.*?/ )[1]
|
13
|
-
|
14
|
-
|
15
|
-
ses['data']
|
14
|
+
result = @sessions.find_one( { :_id => session_id } )
|
15
|
+
result.should_not be_nil
|
16
|
+
ses = YAML.load( result['data'] )
|
17
|
+
ses[key.to_s].should == val
|
16
18
|
end
|
17
19
|
|
18
20
|
def clear_sessions
|
data/tasks/gem.rake
CHANGED
@@ -50,7 +50,7 @@ class GemPackageTask < Rake::PackageTask
|
|
50
50
|
task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
|
51
51
|
file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
|
52
52
|
when_writing("Creating GEM") {
|
53
|
-
chdir(package_dir_path) do
|
53
|
+
chdir(package_dir_path) do
|
54
54
|
Gem::Builder.new(gem_spec).build
|
55
55
|
verbose(true) {
|
56
56
|
mv gem_file, "../#{gem_file}"
|
data/tasks/rdoc.rake
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rake/rdoctask'
|
2
|
+
# require 'darkfish-rdoc'
|
2
3
|
|
3
4
|
namespace :doc do
|
4
5
|
|
@@ -26,8 +27,8 @@ namespace :doc do
|
|
26
27
|
|
27
28
|
rd.options << "-t #{title}"
|
28
29
|
rd.options << "-SHN"
|
29
|
-
|
30
|
-
#
|
30
|
+
rd.options << "-f"
|
31
|
+
# rd.options << "darkfish"
|
31
32
|
rd.options.concat(rdoc.opts)
|
32
33
|
end
|
33
34
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo_rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernand Galiana
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-02-03 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 1.0.
|
23
|
+
version: 1.0.1
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mongo
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.18.
|
33
|
+
version: 0.18.2
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: mongo_ext
|
@@ -40,7 +40,17 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.18.
|
43
|
+
version: 0.18.2
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: bones
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.5.1
|
44
54
|
version:
|
45
55
|
description: ""
|
46
56
|
email: fernand.galiana@gmail.com
|
@@ -54,6 +64,8 @@ files:
|
|
54
64
|
- HISTORY
|
55
65
|
- README.rdoc
|
56
66
|
- Rakefile
|
67
|
+
- aa.rb
|
68
|
+
- fred.rb
|
57
69
|
- lib/core_ext/hash.rb
|
58
70
|
- lib/mongo_rack.rb
|
59
71
|
- lib/mongo_rack/session_hash.rb
|