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 +10 -0
- data/lib/rack/session/redis.rb +132 -0
- data/rack-session-redis.gemspec +17 -0
- metadata +77 -0
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
|
+
|