rack-session-redis 0.0.1

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/README ADDED
@@ -0,0 +1,10 @@
1
+ a redis session store for rack. largely based on Rack::Session::Pool.
2
+ this is an initial release, use with care. patches gladly accepted.
3
+
4
+ $ cat config.ru
5
+ require "rack/session/redis"
6
+
7
+ use Rack::Session::Redis(
8
+ :host => "redis://localhost:6379/0",
9
+ :namespace => "rack:session"
10
+ )
@@ -0,0 +1,132 @@
1
+ # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
2
+ # THANKS:
3
+ # apeiros, for session id generation, expiry setup, and threadiness
4
+ # sergio, threadiness and bugreps
5
+
6
+ require 'rack/session/abstract/id'
7
+ require 'redis'
8
+ require 'thread'
9
+
10
+ module Rack
11
+ module Session
12
+
13
+ class Redis < Abstract::ID
14
+ class MarshalledRedis < ::Redis
15
+ def initialize options={}
16
+ @namespace = options.delete(:namespace)
17
+
18
+ super
19
+ end
20
+
21
+ def get key
22
+ raw = super namespace(key)
23
+ Marshal.load raw if raw
24
+ end
25
+
26
+ def set key, value
27
+ raw = Marshal.dump value
28
+ super namespace(key), raw
29
+ end
30
+
31
+ def del key
32
+ super namespace(key)
33
+ end
34
+
35
+ def setex key, time, value
36
+ raw = Marshal.dump value
37
+ super namespace(key), time, raw
38
+ end
39
+
40
+ private
41
+ def namespace key
42
+ @namespace ? "#{@namespace}:#{key}" : key
43
+ end
44
+ end
45
+
46
+ attr_reader :mutex, :redis
47
+ DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge(
48
+ :drop => false,
49
+ :url => "redis://127.0.0.1:6379/0",
50
+ :namespace => "rack:session"
51
+ )
52
+
53
+ def initialize(app, options={})
54
+ super
55
+
56
+ @redis = MarshalledRedis.new(
57
+ :namespace => default_options[:namespace],
58
+ :url => default_options[:url]
59
+ )
60
+ @mutex = Mutex.new
61
+ end
62
+
63
+ def generate_sid
64
+ loop do
65
+ sid = super
66
+ break sid unless @redis.exists(sid)
67
+ end
68
+ end
69
+
70
+ def get_session(env, sid)
71
+ session = @redis.get(sid) if sid
72
+ @mutex.lock if env['rack.multithread']
73
+ unless sid and session
74
+ env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil?
75
+ session = {}
76
+ sid = generate_sid
77
+ @redis.set sid, session
78
+ end
79
+ session.instance_variable_set('@old', {}.merge(session))
80
+ return [sid, session]
81
+ ensure
82
+ @mutex.unlock if env['rack.multithread']
83
+ end
84
+
85
+ def set_session(env, session_id, new_session, options)
86
+ @mutex.lock if env['rack.multithread']
87
+ session = @redis.get(session_id)
88
+ if options[:renew] or options[:drop]
89
+ @redis.del session_id
90
+ return false if options[:drop]
91
+ session_id = generate_sid
92
+ @redis.set session_id, 0
93
+ end
94
+ old_session = new_session.instance_variable_get('@old') || {}
95
+ session = merge_sessions session_id, old_session, new_session, session
96
+ if options[:expire_after].to_i > 0
97
+ @redis.setex session_id, options[:expire_after], session
98
+ else
99
+ @redis.set session_id, session
100
+ end
101
+ return session_id
102
+ rescue => e
103
+ puts e
104
+ puts e.backtrace
105
+ warn "#{new_session.inspect} has been lost."
106
+ warn $!.inspect
107
+ ensure
108
+ @mutex.unlock if env['rack.multithread']
109
+ end
110
+
111
+ private
112
+
113
+ def merge_sessions sid, old, new, cur=nil
114
+ cur ||= {}
115
+ unless Hash === old and Hash === new
116
+ warn 'Bad old or new sessions provided.'
117
+ return cur
118
+ end
119
+
120
+ delete = old.keys - new.keys
121
+ warn "//@#{sid}: dropping #{delete*','}" if $DEBUG and not delete.empty?
122
+ delete.each{|k| cur.delete k }
123
+
124
+ update = new.keys.select{|k| new[k] != old[k] }
125
+ warn "//@#{sid}: updating #{update*','}" if $DEBUG and not update.empty?
126
+ update.each{|k| cur[k] = new[k] }
127
+
128
+ cur
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "rack-session-redis"
3
+ s.version = "0.0.1"
4
+ s.date = "2010-06-22"
5
+ s.summary = "redis session store for rack"
6
+ s.email = "harry@vangberg.name"
7
+ s.homepage = "http://github.com/ichverstehe/rack-session-redis"
8
+ s.description = "redis session store for rack"
9
+ s.authors = ["Harry Vangberg"]
10
+ s.files = [
11
+ "README",
12
+ "rack-session-redis.gemspec",
13
+ "lib/rack/session/redis.rb",
14
+ ]
15
+ s.add_dependency "redis", ">= 2.0.0"
16
+ end
17
+
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-session-redis
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Harry Vangberg
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-22 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: redis
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 0
30
+ - 0
31
+ version: 2.0.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: redis session store for rack
35
+ email: harry@vangberg.name
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - README
44
+ - rack-session-redis.gemspec
45
+ - lib/rack/session/redis.rb
46
+ has_rdoc: true
47
+ homepage: http://github.com/ichverstehe/rack-session-redis
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options: []
52
+
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.3.6
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: redis session store for rack
76
+ test_files: []
77
+