mongo_rack 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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.0"
30
- depend_on "mongo" , ">= 0.18.1"
31
- depend_on "mongo_ext", ">= 0.18.1"
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
@@ -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( host, port,
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
- session = MongoRack::SessionHash.new( ses_obj['data'] ) if ses_obj and fresh?( ses_obj )
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
- env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil?
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
- session.instance_variable_set( '@old', MongoRack::SessionHash.new.merge(session) )
104
- return [sid, session]
105
- rescue => boom
106
- warn "#{self} is unable to find server."
107
- warn $!.inspect
108
- return [ nil, {} ]
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 = MongoRack::SessionHash.new( ses_obj['data'] )
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
- sessions.save( { :_id => sid, :data => merged, :expire => expiry } )
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
- warn "#{self} is unable to find server."
137
- warn $!.inspect
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
- warn 'Bad old or new sessions provided.'
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
- warn "//@#{sid}: delete #{delete*','}" if $VERBOSE and not delete.empty?
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{ |k| new_s[k] != old_s[k] }
153
- warn "//@#{sid}: update #{update*','}" if $VERBOSE and not update.empty?
154
- update.each{ |k| cur[k] = new_s[k] }
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
@@ -1,10 +1,11 @@
1
- require File.expand_path( File.join( File.dirname(__FILE__), %w[spec_helper] ) )
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 = 'mongo_test'
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 ).body.should == '{"counter"=>2}'
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 ).body.should == '{"counter"=>3}'
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'}, [env['rack.session'].inspect]]
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
- session = @pool.sessions.find_one( {:_id => sess_id } )
202
- session['data'].size.should == 1
203
- session['data']['counter'].should be_nil
204
- session['data'].should == {"foo"=>"bar"}
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
@@ -1,5 +1,4 @@
1
- require File.expand_path( File.join( File.dirname(__FILE__), %w[spec_helper] ) )
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
@@ -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
- ses = @sessions.find_one( { :_id => session_id } )
14
- ses.should_not be_nil
15
- ses['data'][key.to_s].should == val
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
@@ -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}"
@@ -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
- # rd.options << "-f"
30
- # rd.options << "darkfish"
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.2
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-01-05 00:00:00 -07:00
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.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.1
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.1
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