mongo-store 0.1.2 → 0.2.0

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 CHANGED
@@ -29,7 +29,6 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
29
  spec.rcov = true
30
30
  end
31
31
 
32
- task :spec => :check_dependencies
33
32
 
34
33
  task :default => :spec
35
34
 
data/VERSION CHANGED
@@ -1 +1,2 @@
1
- 0.1.2
1
+ 0.2.0
2
+
@@ -11,10 +11,10 @@ module Rack
11
11
  #
12
12
  # == Usage Example
13
13
  #
14
- # use Rack::Session::Mongo, :connection => @existing_mongodb_connection,
14
+ # use Rack::Session::Mongo, :connection => @existing_mongodb_connection;,
15
15
  # :expire_after => 1800
16
16
  class Mongo < Abstract::ID
17
- attr_reader :mutex, :pool, :connection
17
+ attr_reader :mutex, :pool, :connection, :marshal_data
18
18
  DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge :db => 'rack', :collection => 'sessions', :drop => false
19
19
 
20
20
  # Creates a new Mongo session store pool. You probably won't initialize
@@ -35,10 +35,27 @@ module Rack
35
35
  # instance global</i>
36
36
  # @option options [String] :collection ('sessions') the Mongo collection
37
37
  # to use. — <i>pool instance global</i>
38
+ # @option options [boolean] :marshal_data (true) Marshal data into string
39
+ # otherwise store as hash in db. — <i>pool instance global</i>
40
+ # Note: if you use this then the keys used to lookup values must be strings
41
+ # even if you put in symbols. *Example:*
42
+ # request1: session[:test] = true
43
+ # request2: session[:test]
44
+ # > nil
45
+ # session['test']
46
+ # > true
47
+ #
48
+ # The advantage is that you can query the contents of the sessions and
49
+ # potentially make changes on the fly
38
50
  # @option options [Integer] :expire_after (nil) the time in seconds for
39
51
  # the session to last for. *Example:* If this is set to +1800+, the
40
52
  # session will be deleted if the client doesn't make a request within 30
41
53
  # minutes of its last request.
54
+ # @option options [Integer] :clear_expired_after (1800) the time in seconds
55
+ # before we clear out old sessions. *Example:* If this is set to +1800+, the
56
+ # the session will be cleared from mongodb when a session is requested, if
57
+ # it has been 1800 seconds since it was last cleared. setting to -1 will
58
+ # disable this.
42
59
  # @option options [true, false] :defer (false) don't set the session
43
60
  # cookie for this request.
44
61
  # @option options [true, false] :renew (false) causes the generation of
@@ -58,7 +75,11 @@ module Rack
58
75
  @mutex = Mutex.new
59
76
  @connection = @default_options[:connection] || ::Mongo::Connection.new
60
77
  @pool = @connection.db(@default_options[:db]).collection(@default_options[:collection])
78
+ @pool.create_index([['expires', -1]])
61
79
  @pool.create_index('sid', :unique => true)
80
+ @marshal_data = @default_options[:marshal_data].nil? ? true : @default_options[:marshal_data] == true
81
+ @next_expire_period = nil
82
+ @recheck_expire_period = @default_options[:clear_expired_after].nil? ? 1800 : @default_options[:clear_expired_after].to_i
62
83
  end
63
84
 
64
85
  def get_session(env, sid)
@@ -71,6 +92,7 @@ module Rack
71
92
  save_session(sid)
72
93
  end
73
94
  session.instance_variable_set('@old', {}.merge(session))
95
+ session.instance_variable_set('@sid', sid)
74
96
  return [sid, session]
75
97
  ensure
76
98
  @mutex.unlock if env['rack.multithread']
@@ -95,16 +117,25 @@ module Rack
95
117
  end
96
118
 
97
119
  private
120
+
98
121
  def generate_sid
99
122
  loop do
100
123
  sid = super
101
124
  break sid unless find_session(sid)
102
125
  end
103
126
  end
104
-
127
+
105
128
  def find_session(sid)
106
- @pool.remove :expires => {'$lte' => Time.now} # clean out expired sessions
129
+ time = Time.now
130
+ if @recheck_expire_period != -1 && (@next_expire_period.nil? || @next_expire_period < time)
131
+ @next_expire_period = time + @recheck_expire_period
132
+ @pool.remove :expires => {'$lte' => time} # clean out expired sessions
133
+ end
107
134
  session = @pool.find_one :sid => sid
135
+ #if session is expired but hasn't been cleared yet. don't return it.
136
+ if session && session['expires'] != nil && session['expires'] < time
137
+ session = nil
138
+ end
108
139
  session ? unpack(session['data']) : false
109
140
  end
110
141
 
@@ -113,7 +144,7 @@ module Rack
113
144
  end
114
145
 
115
146
  def save_session(sid, session={}, expires=nil)
116
- @pool.update({:sid => sid}, {:sid => sid, :data => pack(session), :expires => expires}, :upsert => true)
147
+ @pool.update({:sid => sid}, {"$set" => {:data => pack(session), :expires => expires}}, :upsert => true)
117
148
  end
118
149
 
119
150
  def merge_sessions(sid, old, new, current=nil)
@@ -127,7 +158,7 @@ module Rack
127
158
  warn "//@#{sid}: dropping #{delete*','}" if $DEBUG and not delete.empty?
128
159
  delete.each{|k| current.delete k }
129
160
 
130
- update = new.keys.select{|k| new[k] != old[k] }
161
+ update = new.keys.select{|k| new[k] != old[k] || new[k].kind_of?(Hash) || new[k].kind_of?(Array) }
131
162
  warn "//@#{sid}: updating #{update*','}" if $DEBUG and not update.empty?
132
163
  update.each{|k| current[k] = new[k] }
133
164
 
@@ -135,12 +166,20 @@ module Rack
135
166
  end
136
167
 
137
168
  def pack(data)
138
- [Marshal.dump(data)].pack("m*")
169
+ if(@marshal_data)
170
+ [Marshal.dump(data)].pack("m*")
171
+ else
172
+ data
173
+ end
139
174
  end
140
175
 
141
176
  def unpack(packed)
142
177
  return nil unless packed
143
- Marshal.load(packed.unpack("m*").first)
178
+ if(@marshal_data)
179
+ Marshal.load(packed.unpack("m*").first)
180
+ else
181
+ packed
182
+ end
144
183
  end
145
184
  end
146
185
  end
@@ -1,62 +1,74 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongo-store}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jonathan Rudenberg"]
12
- s.date = %q{2010-10-03}
12
+ s.date = %q{2011-04-26}
13
13
  s.email = %q{jonathan@titanous.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
16
- "README.rdoc"
16
+ "README.rdoc"
17
17
  ]
18
18
  s.files = [
19
19
  ".document",
20
- ".gitignore",
21
- "Gemfile",
22
- "Gemfile.lock",
23
- "LICENSE",
24
- "README.rdoc",
25
- "Rakefile",
26
- "VERSION",
27
- "lib/mongo-store.rb",
28
- "lib/rack/session/mongo.rb",
29
- "mongo-store.gemspec",
30
- "spec/rack-mongo-store_spec.rb",
31
- "spec/spec.opts",
32
- "spec/spec_helper.rb"
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/mongo-store.rb",
27
+ "lib/rack/session/mongo.rb",
28
+ "mongo-store.gemspec",
29
+ "spec/rack-mongo-store_spec.rb",
30
+ "spec/spec.opts",
31
+ "spec/spec_helper.rb"
33
32
  ]
34
33
  s.homepage = %q{http://github.com/titanous/mongo-store}
35
- s.rdoc_options = ["--charset=UTF-8"]
36
34
  s.require_paths = ["lib"]
37
- s.rubygems_version = %q{1.3.7}
35
+ s.rubygems_version = %q{1.7.2}
38
36
  s.summary = %q{Rack session store for MongoDB}
39
37
  s.test_files = [
40
38
  "spec/rack-mongo-store_spec.rb",
41
- "spec/spec_helper.rb"
39
+ "spec/spec_helper.rb"
42
40
  ]
43
41
 
44
42
  if s.respond_to? :specification_version then
45
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
43
  s.specification_version = 3
47
44
 
48
45
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<mongo-store>, [">= 0"])
47
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
48
+ s.add_development_dependency(%q<yard>, [">= 0"])
49
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
50
+ s.add_development_dependency(%q<yard>, [">= 0"])
49
51
  s.add_runtime_dependency(%q<mongo>, [">= 1.0.1"])
50
52
  s.add_runtime_dependency(%q<rack>, [">= 1.1.0"])
51
53
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
52
54
  s.add_development_dependency(%q<yard>, [">= 0"])
53
55
  else
56
+ s.add_dependency(%q<mongo-store>, [">= 0"])
57
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
58
+ s.add_dependency(%q<yard>, [">= 0"])
59
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
60
+ s.add_dependency(%q<yard>, [">= 0"])
54
61
  s.add_dependency(%q<mongo>, [">= 1.0.1"])
55
62
  s.add_dependency(%q<rack>, [">= 1.1.0"])
56
63
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
57
64
  s.add_dependency(%q<yard>, [">= 0"])
58
65
  end
59
66
  else
67
+ s.add_dependency(%q<mongo-store>, [">= 0"])
68
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
69
+ s.add_dependency(%q<yard>, [">= 0"])
70
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
71
+ s.add_dependency(%q<yard>, [">= 0"])
60
72
  s.add_dependency(%q<mongo>, [">= 1.0.1"])
61
73
  s.add_dependency(%q<rack>, [">= 1.1.0"])
62
74
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
@@ -27,15 +27,14 @@ describe 'Rack::Session::Mongo' do
27
27
  it 'should specify connection params' do
28
28
  mongo = Rack::Session::Mongo.new(@incrementor,
29
29
  :connection => Mongo::Connection.new('localhost'), :db => 'rack-test',
30
- :collection => 'mongo-test')
30
+ :collection => 'mongo_test')
31
31
  pool = mongo.pool
32
32
  connection = mongo.connection
33
-
34
- connection.host.should == 'localhost'
33
+ connection.primary[0].should == 'localhost'
35
34
 
36
35
  pool.should be_kind_of(Mongo::Collection)
37
36
  pool.db.name.should == 'rack-test'
38
- pool.name.should == 'mongo-test'
37
+ pool.name.should == 'mongo_test'
39
38
  end
40
39
 
41
40
  it 'creates a new cookie' do
@@ -128,7 +127,20 @@ describe 'Rack::Session::Mongo' do
128
127
  res3['Set-Cookie'][@session_match].should == new_session
129
128
  res3.body.should == '{"counter"=>4}'
130
129
  end
131
-
130
+ it 'should default marshal_data to true' do
131
+ pool = Rack::Session::Mongo.new(@incrementor)
132
+ pool.marshal_data.should == true
133
+ data = {'test' => true}
134
+ pool.send(:pack, data).should == [Marshal.dump(data)].pack("m*")
135
+ pool.send(:unpack, [Marshal.dump(data)].pack("m*"))['test'] == true
136
+ end
137
+ it 'should be able to set marshal_data to false' do
138
+ pool = Rack::Session::Mongo.new(@incrementor, :marshal_data => false)
139
+ pool.marshal_data.should == false
140
+ data = {'test' => true}
141
+ pool.send(:pack, data).should === data
142
+ pool.send(:unpack, data).should === data
143
+ end
132
144
  specify 'omits cookie with :defer option' do
133
145
  pool = Rack::Session::Mongo.new(@incrementor)
134
146
  req = Rack::MockRequest.new(pool)
File without changes
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo-store
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 2
10
- version: 0.1.2
4
+ prerelease:
5
+ version: 0.2.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Jonathan Rudenberg
@@ -15,71 +10,107 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2010-10-03 00:00:00 -04:00
19
- default_executable:
13
+ date: 2011-04-26 00:00:00 Z
20
14
  dependencies:
21
15
  - !ruby/object:Gem::Dependency
22
- name: mongo
23
- prerelease: false
16
+ name: mongo-store
24
17
  requirement: &id001 !ruby/object:Gem::Requirement
25
18
  none: false
26
19
  requirements:
27
20
  - - ">="
28
21
  - !ruby/object:Gem::Version
29
- hash: 21
30
- segments:
31
- - 1
32
- - 0
33
- - 1
34
- version: 1.0.1
22
+ version: "0"
35
23
  type: :runtime
24
+ prerelease: false
36
25
  version_requirements: *id001
37
26
  - !ruby/object:Gem::Dependency
38
- name: rack
39
- prerelease: false
27
+ name: rspec
40
28
  requirement: &id002 !ruby/object:Gem::Requirement
41
29
  none: false
42
30
  requirements:
43
31
  - - ">="
44
32
  - !ruby/object:Gem::Version
45
- hash: 19
46
- segments:
47
- - 1
48
- - 1
49
- - 0
50
- version: 1.1.0
51
- type: :runtime
33
+ version: 1.2.9
34
+ type: :development
35
+ prerelease: false
52
36
  version_requirements: *id002
53
37
  - !ruby/object:Gem::Dependency
54
- name: rspec
55
- prerelease: false
38
+ name: yard
56
39
  requirement: &id003 !ruby/object:Gem::Requirement
57
40
  none: false
58
41
  requirements:
59
42
  - - ">="
60
43
  - !ruby/object:Gem::Version
61
- hash: 13
62
- segments:
63
- - 1
64
- - 2
65
- - 9
66
- version: 1.2.9
44
+ version: "0"
67
45
  type: :development
46
+ prerelease: false
68
47
  version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 1.2.9
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
69
59
  - !ruby/object:Gem::Dependency
70
60
  name: yard
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ type: :development
71
68
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: mongo
72
+ requirement: &id006 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.1
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: *id006
81
+ - !ruby/object:Gem::Dependency
82
+ name: rack
83
+ requirement: &id007 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.1.0
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: *id007
92
+ - !ruby/object:Gem::Dependency
93
+ name: rspec
94
+ requirement: &id008 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 1.2.9
100
+ type: :development
101
+ prerelease: false
102
+ version_requirements: *id008
103
+ - !ruby/object:Gem::Dependency
104
+ name: yard
105
+ requirement: &id009 !ruby/object:Gem::Requirement
73
106
  none: false
74
107
  requirements:
75
108
  - - ">="
76
109
  - !ruby/object:Gem::Version
77
- hash: 3
78
- segments:
79
- - 0
80
110
  version: "0"
81
111
  type: :development
82
- version_requirements: *id004
112
+ prerelease: false
113
+ version_requirements: *id009
83
114
  description:
84
115
  email: jonathan@titanous.com
85
116
  executables: []
@@ -91,7 +122,6 @@ extra_rdoc_files:
91
122
  - README.rdoc
92
123
  files:
93
124
  - .document
94
- - .gitignore
95
125
  - Gemfile
96
126
  - Gemfile.lock
97
127
  - LICENSE
@@ -104,13 +134,12 @@ files:
104
134
  - spec/rack-mongo-store_spec.rb
105
135
  - spec/spec.opts
106
136
  - spec/spec_helper.rb
107
- has_rdoc: true
108
137
  homepage: http://github.com/titanous/mongo-store
109
138
  licenses: []
110
139
 
111
140
  post_install_message:
112
- rdoc_options:
113
- - --charset=UTF-8
141
+ rdoc_options: []
142
+
114
143
  require_paths:
115
144
  - lib
116
145
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -118,23 +147,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
147
  requirements:
119
148
  - - ">="
120
149
  - !ruby/object:Gem::Version
121
- hash: 3
122
- segments:
123
- - 0
124
150
  version: "0"
125
151
  required_rubygems_version: !ruby/object:Gem::Requirement
126
152
  none: false
127
153
  requirements:
128
154
  - - ">="
129
155
  - !ruby/object:Gem::Version
130
- hash: 3
131
- segments:
132
- - 0
133
156
  version: "0"
134
157
  requirements: []
135
158
 
136
159
  rubyforge_project:
137
- rubygems_version: 1.3.7
160
+ rubygems_version: 1.7.2
138
161
  signing_key:
139
162
  specification_version: 3
140
163
  summary: Rack session store for MongoDB
data/.gitignore DELETED
@@ -1,23 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- doc
19
- .yardoc
20
- pkg
21
-
22
- ## PROJECT::SPECIFIC
23
- .bundle