Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
hanoi2005
redis
提交
0df1ead7
R
redis
项目概览
hanoi2005
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0df1ead7
编写于
6月 10, 2009
作者:
A
antirez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
sync with jodosha redis-rb
上级
38210f7f
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
437 addition
and
640 deletion
+437
-640
client-libraries/ruby/lib/dist_redis.rb
client-libraries/ruby/lib/dist_redis.rb
+13
-6
client-libraries/ruby/lib/pipeline.rb
client-libraries/ruby/lib/pipeline.rb
+6
-12
client-libraries/ruby/lib/redis.rb
client-libraries/ruby/lib/redis.rb
+231
-405
client-libraries/ruby/redis-rb.gemspec
client-libraries/ruby/redis-rb.gemspec
+1
-1
client-libraries/ruby/spec/redis_spec.rb
client-libraries/ruby/spec/redis_spec.rb
+184
-215
client-libraries/update-ruby-client.sh
client-libraries/update-ruby-client.sh
+2
-1
未找到文件。
client-libraries/ruby/lib/dist_redis.rb
浏览文件 @
0df1ead7
...
...
@@ -2,13 +2,20 @@ require 'redis'
require
'hash_ring'
class
DistRedis
attr_reader
:ring
def
initialize
(
*
servers
)
srvs
=
[]
servers
.
each
do
|
s
|
server
,
port
=
s
.
split
(
':'
)
srvs
<<
Redis
.
new
(
:host
=>
server
,
:port
=>
port
)
def
initialize
(
opts
=
{})
hosts
=
[]
db
=
opts
[
:db
]
||
nil
timeout
=
opts
[
:timeout
]
||
nil
raise
Error
,
"No hosts given"
unless
opts
[
:hosts
]
opts
[
:hosts
].
each
do
|
h
|
host
,
port
=
h
.
split
(
':'
)
hosts
<<
Redis
.
new
(
:host
=>
host
,
:port
=>
port
,
:db
=>
db
,
:timeout
=>
timeout
,
:db
=>
db
)
end
@ring
=
HashRing
.
new
srvs
@ring
=
HashRing
.
new
hosts
end
def
node_for_key
(
key
)
...
...
client-libraries/ruby/lib/pipeline.rb
浏览文件 @
0df1ead7
...
...
@@ -8,19 +8,13 @@ class Redis
@redis
=
redis
@commands
=
[]
end
def
execute_command
(
data
)
@commands
<<
data
write_and_read
if
@commands
.
size
>=
BUFFER_SIZE
end
def
finish
write_and_read
def
call_command
(
command
)
@commands
<<
command
end
def
write_and_read
@redis
.
execute_command
(
@commands
.
join
,
true
)
@redis
.
read_socket
def
execute
@redis
.
call_command
(
@commands
)
@commands
.
clear
end
...
...
client-libraries/ruby/lib/redis.rb
浏览文件 @
0df1ead7
require
'socket'
require
'set'
require
File
.
join
(
File
.
dirname
(
__FILE__
),
'server'
)
require
File
.
join
(
File
.
dirname
(
__FILE__
),
'pipeline'
)
class
RedisError
<
StandardError
end
class
RedisRenameError
<
StandardError
begin
if
RUBY_VERSION
>=
'1.9'
require
'timeout'
RedisTimer
=
Timeout
else
require
'system_timer'
RedisTimer
=
SystemTimer
end
rescue
LoadError
RedisTimer
=
nil
end
class
Redis
ERR
=
"-"
.
freeze
OK
=
'OK'
.
freeze
PONG
=
'PONG'
.
freeze
SINGLE
=
'+'
.
freeze
BULK
=
'$'
.
freeze
MULTI
=
'*'
.
freeze
INT
=
':'
.
freeze
attr_reader
:server
def
initialize
(
opts
=
{})
@opts
=
{
:host
=>
'localhost'
,
:port
=>
'6379'
,
:db
=>
0
}.
merge
(
opts
)
$debug
=
@opts
[
:debug
]
@db
=
@opts
[
:db
]
@server
=
Server
.
new
(
@opts
[
:host
],
@opts
[
:port
],
(
@opts
[
:timeout
]
||
10
))
end
def
pipelined
pipeline
=
Pipeline
.
new
(
self
)
yield
pipeline
pipeline
.
finish
OK
=
"OK"
.
freeze
MINUS
=
"-"
.
freeze
PLUS
=
"+"
.
freeze
COLON
=
":"
.
freeze
DOLLAR
=
"$"
.
freeze
ASTERISK
=
"*"
.
freeze
BULK_COMMANDS
=
{
"set"
=>
true
,
"setnx"
=>
true
,
"rpush"
=>
true
,
"lpush"
=>
true
,
"lset"
=>
true
,
"lrem"
=>
true
,
"sadd"
=>
true
,
"srem"
=>
true
,
"sismember"
=>
true
,
"echo"
=>
true
,
"getset"
=>
true
,
"smove"
=>
true
}
BOOLEAN_PROCESSOR
=
lambda
{
|
r
|
r
==
0
?
false
:
r
}
REPLY_PROCESSOR
=
{
"exists"
=>
BOOLEAN_PROCESSOR
,
"sismember"
=>
BOOLEAN_PROCESSOR
,
"sadd"
=>
BOOLEAN_PROCESSOR
,
"srem"
=>
BOOLEAN_PROCESSOR
,
"smove"
=>
BOOLEAN_PROCESSOR
,
"move"
=>
BOOLEAN_PROCESSOR
,
"setnx"
=>
BOOLEAN_PROCESSOR
,
"del"
=>
BOOLEAN_PROCESSOR
,
"renamenx"
=>
BOOLEAN_PROCESSOR
,
"expire"
=>
BOOLEAN_PROCESSOR
,
"keys"
=>
lambda
{
|
r
|
r
.
split
(
" "
)},
"info"
=>
lambda
{
|
r
|
info
=
{}
r
.
each_line
{
|
kv
|
k
,
v
=
kv
.
split
(
":"
,
2
).
map
{
|
x
|
x
.
chomp
}
info
[
k
.
to_sym
]
=
v
}
info
}
}
ALIASES
=
{
"flush_db"
=>
"flushdb"
,
"flush_all"
=>
"flushall"
,
"last_save"
=>
"lastsave"
,
"key?"
=>
"exists"
,
"delete"
=>
"del"
,
"randkey"
=>
"randomkey"
,
"list_length"
=>
"llen"
,
"push_tail"
=>
"rpush"
,
"push_head"
=>
"lpush"
,
"pop_tail"
=>
"rpop"
,
"pop_head"
=>
"lpop"
,
"list_set"
=>
"lset"
,
"list_range"
=>
"lrange"
,
"list_trim"
=>
"ltrim"
,
"list_index"
=>
"lindex"
,
"list_rm"
=>
"lrem"
,
"set_add"
=>
"sadd"
,
"set_delete"
=>
"srem"
,
"set_count"
=>
"scard"
,
"set_member?"
=>
"sismember"
,
"set_members"
=>
"smembers"
,
"set_intersect"
=>
"sinter"
,
"set_intersect_store"
=>
"sinterstore"
,
"set_inter_store"
=>
"sinterstore"
,
"set_union"
=>
"sunion"
,
"set_union_store"
=>
"sunionstore"
,
"set_diff"
=>
"sdiff"
,
"set_diff_store"
=>
"sdiffstore"
,
"set_move"
=>
"smove"
,
"set_unless_exists"
=>
"setnx"
,
"rename_unless_exists"
=>
"renamenx"
,
"type?"
=>
"type"
}
def
initialize
(
options
=
{})
@host
=
options
[
:host
]
||
'127.0.0.1'
@port
=
(
options
[
:port
]
||
6379
).
to_i
@db
=
(
options
[
:db
]
||
0
).
to_i
@timeout
=
(
options
[
:timeout
]
||
5
).
to_i
$debug
=
options
[
:debug
]
connect_to_server
end
def
to_s
"
#{
host
}
:
#{
port
}
->
#{
@db
}
"
end
def
port
@opts
[
:port
]
end
def
host
@opts
[
:host
]
end
def
quit
execute_command
(
"QUIT
\r\n
"
,
true
)
end
def
ping
execute_command
(
"PING
\r\n
"
)
==
PONG
"Redis Client connected to
#{
@host
}
:
#{
@port
}
against DB
#{
@db
}
"
end
def
select_db
(
index
)
@db
=
index
execute_command
(
"SELECT
#{
index
}
\r\n
"
)
end
def
flush_db
execute_command
(
"FLUSHDB
\r\n
"
)
==
OK
end
def
flush_all
puts
"Warning!
\n
Flushing *ALL* databases!
\n
5 Seconds to Hit ^C!"
trap
(
'INT'
)
{
quit
;
return
false
}
sleep
5
execute_command
(
"FLUSHALL
\r\n
"
)
==
OK
end
def
last_save
execute_command
(
"LASTSAVE
\r\n
"
).
to_i
end
def
bgsave
execute_command
(
"BGSAVE
\r\n
"
)
==
OK
end
def
info
info
=
{}
x
=
execute_command
(
"INFO
\r\n
"
)
x
.
each_line
do
|
kv
|
k
,
v
=
kv
.
split
(
':'
,
2
)
k
,
v
=
k
.
chomp
,
v
=
v
.
chomp
info
[
k
.
to_sym
]
=
v
end
info
end
def
keys
(
glob
)
execute_command
(
"KEYS
#{
glob
}
\r\n
"
).
split
(
' '
)
def
connect_to_server
@sock
=
connect_to
(
@host
,
@port
,
@timeout
==
0
?
nil
:
@timeout
)
call_command
([
"select"
,
@db
])
unless
@db
==
0
end
def
rename!
(
oldkey
,
newkey
)
execute_command
(
"RENAME
#{
oldkey
}
#{
newkey
}
\r\n
"
)
end
def
rename
(
oldkey
,
newkey
)
case
execute_command
(
"RENAMENX
#{
oldkey
}
#{
newkey
}
\r\n
"
)
when
-
1
raise
RedisRenameError
,
"source key:
#{
oldkey
}
does not exist"
when
0
raise
RedisRenameError
,
"target key:
#{
oldkey
}
already exists"
when
-
3
raise
RedisRenameError
,
"source and destination keys are the same"
when
1
true
def
connect_to
(
host
,
port
,
timeout
=
nil
)
# We support connect() timeout only if system_timer is availabe
# or if we are running against Ruby >= 1.9
# Timeout reading from the socket instead will be supported anyway.
if
@timeout
!=
0
and
RedisTimer
begin
sock
=
TCPSocket
.
new
(
host
,
port
)
rescue
Timeout
::
Error
@sock
=
nil
raise
Timeout
::
Error
,
"Timeout connecting to the server"
end
else
sock
=
TCPSocket
.
new
(
host
,
port
)
end
end
def
key?
(
key
)
execute_command
(
"EXISTS
#{
key
}
\r\n
"
)
==
1
end
def
delete
(
key
)
execute_command
(
"DEL
#{
key
}
\r\n
"
)
==
1
end
def
[]
(
key
)
get
(
key
)
sock
.
setsockopt
Socket
::
IPPROTO_TCP
,
Socket
::
TCP_NODELAY
,
1
# If the timeout is set we set the low level socket options in order
# to make sure a blocking read will return after the specified number
# of seconds. This hack is from memcached ruby client.
if
timeout
secs
=
Integer
(
timeout
)
usecs
=
Integer
((
timeout
-
secs
)
*
1_000_000
)
optval
=
[
secs
,
usecs
].
pack
(
"l_2"
)
sock
.
setsockopt
Socket
::
SOL_SOCKET
,
Socket
::
SO_RCVTIMEO
,
optval
sock
.
setsockopt
Socket
::
SOL_SOCKET
,
Socket
::
SO_SNDTIMEO
,
optval
end
sock
end
def
get
(
key
)
execute_command
(
"GET
#{
key
}
\r\n
"
)
end
def
mget
(
*
keys
)
execute_command
(
"MGET
#{
keys
.
join
(
' '
)
}
\r\n
"
)
def
method_missing
(
*
argv
)
call_command
(
argv
)
end
def
incr
(
key
,
increment
=
nil
)
if
increment
execute_command
(
"INCRBY
#{
key
}
#{
increment
}
\r\n
"
)
else
execute_command
(
"INCR
#{
key
}
\r\n
"
)
end
def
call_command
(
argv
)
puts
argv
.
inspect
if
$debug
# this wrapper to raw_call_command handle reconnection on socket
# error. We try to reconnect just one time, otherwise let the error
# araise.
connect_to_server
if
!
@sock
begin
raw_call_command
(
argv
.
dup
)
rescue
Errno
::
ECONNRESET
@sock
.
close
connect_to_server
raw_call_command
(
argv
.
dup
)
end
end
def
decr
(
key
,
decrement
=
nil
)
if
decrement
execute_command
(
"DECRBY
#{
key
}
#{
decrement
}
\r\n
"
)
else
execute_command
(
"DECR
#{
key
}
\r\n
"
)
end
end
def
randkey
execute_command
(
"RANDOMKEY
\r\n
"
)
end
def
raw_call_command
(
argvp
)
pipeline
=
argvp
[
0
].
is_a?
(
Array
)
def
list_length
(
key
)
case
i
=
execute_command
(
"LLEN
#{
key
}
\r\n
"
)
when
-
2
raise
RedisError
,
"key:
#{
key
}
does not hold a list value"
unless
pipeline
argvv
=
[
argvp
]
else
i
argvv
=
argvp
end
end
def
type?
(
key
)
execute_command
(
"TYPE
#{
key
}
\r\n
"
)
end
def
push_tail
(
key
,
val
)
execute_command
(
"RPUSH
#{
key
}
#{
value_to_wire
(
val
)
}
\r\n
"
)
end
def
push_head
(
key
,
val
)
execute_command
(
"LPUSH
#{
key
}
#{
value_to_wire
(
val
)
}
\r\n
"
)
end
def
pop_head
(
key
)
execute_command
(
"LPOP
#{
key
}
\r\n
"
)
end
def
pop_tail
(
key
)
execute_command
(
"RPOP
#{
key
}
\r\n
"
)
end
def
list_set
(
key
,
index
,
val
)
execute_command
(
"LSET
#{
key
}
#{
index
}
#{
value_to_wire
(
val
)
}
\r\n
"
)
==
OK
end
def
list_range
(
key
,
start
,
ending
)
execute_command
(
"LRANGE
#{
key
}
#{
start
}
#{
ending
}
\r\n
"
)
end
command
=
''
def
list_trim
(
key
,
start
,
ending
)
execute_command
(
"LTRIM
#{
key
}
#{
start
}
#{
ending
}
\r\n
"
)
end
def
list_index
(
key
,
index
)
execute_command
(
"LINDEX
#{
key
}
#{
index
}
\r\n
"
)
end
def
list_rm
(
key
,
count
,
val
)
case
num
=
execute_command
(
"LREM
#{
key
}
#{
count
}
#{
value_to_wire
(
val
)
}
\r\n
"
)
when
-
1
raise
RedisError
,
"key:
#{
key
}
does not exist"
when
-
2
raise
RedisError
,
"key:
#{
key
}
does not hold a list value"
else
num
end
end
def
set_add
(
key
,
member
)
case
execute_command
(
"SADD
#{
key
}
#{
value_to_wire
(
member
)
}
\r\n
"
)
when
1
true
when
0
false
when
-
2
raise
RedisError
,
"key:
#{
key
}
contains a non set value"
argvv
.
each
do
|
argv
|
bulk
=
nil
argv
[
0
]
=
argv
[
0
].
to_s
.
downcase
argv
[
0
]
=
ALIASES
[
argv
[
0
]]
if
ALIASES
[
argv
[
0
]]
if
BULK_COMMANDS
[
argv
[
0
]]
and
argv
.
length
>
1
bulk
=
argv
[
-
1
].
to_s
argv
[
-
1
]
=
bulk
.
length
end
command
<<
argv
.
join
(
' '
)
+
"
\r\n
"
command
<<
bulk
+
"
\r\n
"
if
bulk
end
end
def
set_delete
(
key
,
member
)
case
execute_command
(
"SREM
#{
key
}
#{
value_to_wire
(
member
)
}
\r\n
"
)
when
1
true
when
0
false
when
-
2
raise
RedisError
,
"key:
#{
key
}
contains a non set value"
end
end
@sock
.
write
(
command
)
def
set_count
(
key
)
case
i
=
execute_command
(
"SCARD
#{
key
}
\r\n
"
)
when
-
2
raise
RedisError
,
"key:
#{
key
}
contains a non set value"
else
i
results
=
argvv
.
map
do
|
argv
|
processor
=
REPLY_PROCESSOR
[
argv
[
0
]]
processor
?
processor
.
call
(
read_reply
)
:
read_reply
end
end
def
set_member?
(
key
,
member
)
case
execute_command
(
"SISMEMBER
#{
key
}
#{
value_to_wire
(
member
)
}
\r\n
"
)
when
1
true
when
0
false
when
-
2
raise
RedisError
,
"key:
#{
key
}
contains a non set value"
end
return
pipeline
?
results
:
results
[
0
]
end
def
se
t_members
(
key
)
Set
.
new
(
execute_command
(
"SMEMBERS
#{
key
}
\r\n
"
))
def
se
lect
(
*
args
)
raise
"SELECT not allowed, use the :db option when creating the object"
end
def
set_intersect
(
*
keys
)
Set
.
new
(
execute_command
(
"SINTER
#{
keys
.
join
(
' '
)
}
\r\n
"
)
)
def
[]
(
key
)
get
(
key
)
end
def
set_inter_store
(
destkey
,
*
keys
)
execute_command
(
"SINTERSTORE
#{
destkey
}
#{
keys
.
join
(
' '
)
}
\r\n
"
)
end
def
set_union
(
*
keys
)
Set
.
new
(
execute_command
(
"SUNION
#{
keys
.
join
(
' '
)
}
\r\n
"
))
def
[]=
(
key
,
value
)
set
(
key
,
value
)
end
def
set_union_store
(
destkey
,
*
keys
)
execute_command
(
"SUNIONSTORE
#{
destkey
}
#{
keys
.
join
(
' '
)
}
\r\n
"
)
end
def
set_diff
(
*
keys
)
Set
.
new
(
execute_command
(
"SDIFF
#{
keys
.
join
(
' '
)
}
\r\n
"
))
def
set
(
key
,
value
,
expiry
=
nil
)
s
=
call_command
([
:set
,
key
,
value
])
==
OK
expire
(
key
,
expiry
)
if
s
&&
expiry
s
end
def
set_diff_store
(
destkey
,
*
keys
)
execute_command
(
"SDIFFSTORE
#{
destkey
}
#{
keys
.
join
(
' '
)
}
\r\n
"
)
def
sort
(
key
,
options
=
{})
cmd
=
[]
cmd
<<
"SORT
#{
key
}
"
cmd
<<
"BY
#{
options
[
:by
]
}
"
if
options
[
:by
]
cmd
<<
"GET
#{
[
options
[
:get
]].
flatten
*
' GET '
}
"
if
options
[
:get
]
cmd
<<
"
#{
options
[
:order
]
}
"
if
options
[
:order
]
cmd
<<
"LIMIT
#{
options
[
:limit
].
join
(
' '
)
}
"
if
options
[
:limit
]
call_command
(
cmd
)
end
def
set_move
(
srckey
,
destkey
,
member
)
execute_command
(
"SMOVE
#{
srckey
}
#{
destkey
}
#{
value_to_wire
(
member
)
}
\r\n
"
)
==
1
def
incr
(
key
,
increment
=
nil
)
call_command
(
increment
?
[
"incrby"
,
key
,
increment
]
:
[
"incr"
,
key
])
end
def
sort
(
key
,
opts
=
{})
cmd
=
"SORT
#{
key
}
"
cmd
<<
" BY
#{
opts
[
:by
]
}
"
if
opts
[
:by
]
cmd
<<
" GET
#{
[
opts
[
:get
]].
flatten
*
' GET '
}
"
if
opts
[
:get
]
cmd
<<
" INCR
#{
opts
[
:incr
]
}
"
if
opts
[
:incr
]
cmd
<<
" DEL
#{
opts
[
:del
]
}
"
if
opts
[
:del
]
cmd
<<
" DECR
#{
opts
[
:decr
]
}
"
if
opts
[
:decr
]
cmd
<<
"
#{
opts
[
:order
]
}
"
if
opts
[
:order
]
cmd
<<
" LIMIT
#{
opts
[
:limit
].
join
(
' '
)
}
"
if
opts
[
:limit
]
cmd
<<
"
\r\n
"
execute_command
(
cmd
)
end
def
[]=
(
key
,
val
)
set
(
key
,
val
)
end
def
set
(
key
,
val
,
expiry
=
nil
)
s
=
execute_command
(
"SET
#{
key
}
#{
value_to_wire
(
val
)
}
\r\n
"
)
==
OK
return
expire
(
key
,
expiry
)
if
s
&&
expiry
s
def
decr
(
key
,
decrement
=
nil
)
call_command
(
decrement
?
[
"decrby"
,
key
,
decrement
]
:
[
"decr"
,
key
])
end
def
dbsize
execute_command
(
"DBSIZE
\r\n
"
)
# Ruby defines a now deprecated type method so we need to override it here
# since it will never hit method_missing
def
type
(
key
)
call_command
([
'type'
,
key
])
end
def
expire
(
key
,
expiry
=
nil
)
execute_command
(
"EXPIRE
#{
key
}
#{
expiry
}
\r\n
"
)
==
1
def
quit
call_command
([
'quit'
])
rescue
Errno
::
ECONNRESET
end
def
set_unless_exists
(
key
,
val
)
execute_command
(
"SETNX
#{
key
}
#{
value_to_wire
(
val
)
}
\r\n
"
)
==
1
end
def
bulk_reply
begin
x
=
read
puts
"bulk_reply read value is
#{
x
.
inspect
}
"
if
$debug
return
x
rescue
=>
e
puts
"error in bulk_reply
#{
e
}
"
if
$debug
nil
end
end
def
write
(
data
)
puts
"writing:
#{
data
}
"
if
$debug
@socket
.
write
(
data
)
end
def
read
(
length
=
0
)
length
=
read_proto
unless
length
>
0
res
=
@socket
.
read
(
length
)
puts
"read is
#{
res
.
inspect
}
"
if
$debug
res
end
def
multi_bulk
res
=
read_proto
puts
"mb res is
#{
res
.
inspect
}
"
if
$debug
list
=
[]
Integer
(
res
).
times
do
vf
=
get_response
puts
"curren vf is
#{
vf
.
inspect
}
"
if
$debug
list
<<
vf
puts
"current list is
#{
list
.
inspect
}
"
if
$debug
end
list
end
def
get_reply
begin
r
=
read
(
1
)
raise
RedisError
if
(
r
==
"
\r
"
||
r
==
"
\n
"
)
rescue
RedisError
retry
end
r
end
def
status_code_reply
begin
res
=
read_proto
if
res
.
index
(
'-'
)
==
0
raise
RedisError
,
res
else
true
end
rescue
RedisError
raise
RedisError
end
end
def
execute_command
(
command
,
ignore_response
=
false
)
ss
=
server
.
socket
unless
ss
.
object_id
==
@socket
.
object_id
@socket
=
ss
puts
"Socket changed, selecting DB"
if
$debug
unless
command
[
0
..
6
]
==
'SELECT'
#BTM - Ugh- DRY but better than infinite recursion
write
(
"SELECT
#{
@db
}
\r\n
"
)
get_response
end
end
write
(
command
)
get_response
unless
ignore_response
rescue
Errno
::
ECONNRESET
,
Errno
::
EPIPE
,
NoMethodError
,
Timeout
::
Error
=>
e
raise
RedisError
,
"Connection error"
def
pipelined
(
&
block
)
pipeline
=
Pipeline
.
new
self
yield
pipeline
pipeline
.
execute
end
def
get_response
rtype
=
get_reply
puts
"reply_type is
#{
rtype
.
inspect
}
"
if
$debug
case
rtype
when
SINGLE
single_line
when
BULK
bulk_reply
when
MULTI
multi_bulk
when
INT
integer_reply
when
ERR
raise
RedisError
,
single_line
else
raise
RedisError
,
"Unknown response.."
end
end
def
integer_reply
Integer
(
read_proto
)
end
def
single_line
buff
=
""
while
buff
[
-
2
..-
1
]
!=
"
\r\n
"
buff
<<
read
(
1
)
end
puts
"single_line value is
#{
buff
[
0
..-
3
].
inspect
}
"
if
$debug
buff
[
0
..-
3
]
end
def
read_socket
def
read_reply
# We read the first byte using read() mainly because gets() is
# immune to raw socket timeouts.
begin
socket
=
@server
.
socket
while
res
=
socket
.
read
(
8096
)
break
if
res
.
size
!=
8096
end
#Timeout or server down
rescue
Errno
::
ECONNRESET
,
Errno
::
EPIPE
,
Errno
::
ECONNREFUSED
=>
e
server
.
close
puts
"Client (
#{
server
.
inspect
}
) disconnected from server:
#{
e
.
inspect
}
\n
"
if
$debug
retry
rescue
Timeout
::
Error
=>
e
#BTM - Ignore this error so we don't go into an endless loop
puts
"Client (
#{
server
.
inspect
}
) Timeout
\n
"
if
$debug
#Server down
rescue
NoMethodError
=>
e
puts
"Client (
#{
server
.
inspect
}
) tryin server that is down:
#{
e
.
inspect
}
\n
Dying!"
if
$debug
raise
Errno
::
ECONNREFUSED
#exit
rtype
=
@sock
.
read
(
1
)
rescue
Errno
::
EAGAIN
# We want to make sure it reconnects on the next command after the
# timeout. Otherwise the server may reply in the meantime leaving
# the protocol in a desync status.
@sock
=
nil
raise
Errno
::
EAGAIN
,
"Timeout reading from the socket"
end
end
def
read_proto
res
=
@socket
.
readline
x
=
res
.
chomp
puts
"read_proto is
#{
x
.
inspect
}
\n\n
"
if
$debug
x
.
to_i
end
private
def
value_to_wire
(
value
)
value_str
=
value
.
to_s
if
value_str
.
respond_to?
(
:bytesize
)
value_size
=
value_str
.
bytesize
raise
Errno
::
ECONNRESET
,
"Connection lost"
if
!
rtype
line
=
@sock
.
gets
case
rtype
when
MINUS
raise
MINUS
+
line
.
strip
when
PLUS
line
.
strip
when
COLON
line
.
to_i
when
DOLLAR
bulklen
=
line
.
to_i
return
nil
if
bulklen
==
-
1
data
=
@sock
.
read
(
bulklen
)
@sock
.
read
(
2
)
# CRLF
data
when
ASTERISK
objects
=
line
.
to_i
return
nil
if
bulklen
==
-
1
res
=
[]
objects
.
times
{
res
<<
read_reply
}
res
else
value_size
=
value_str
.
size
raise
"Protocol error, got '
#{
rtype
}
' as initial reply byte"
end
"
#{
value_size
}
\r\n
#{
value_str
}
"
end
end
client-libraries/ruby/redis-rb.gemspec
浏览文件 @
0df1ead7
...
...
@@ -2,7 +2,7 @@
Gem
::
Specification
.
new
do
|
s
|
s
.
name
=
%q{redis}
s
.
version
=
"0.0.
3.
5"
s
.
version
=
"0.0.5"
s
.
required_rubygems_version
=
Gem
::
Requirement
.
new
(
">= 0"
)
if
s
.
respond_to?
:required_rubygems_version
=
s
.
authors
=
[
"Ezra Zygmuntowicz"
,
"Taylor Weibley"
,
"Matthew Clark"
]
...
...
client-libraries/ruby/spec/redis_spec.rb
浏览文件 @
0df1ead7
...
...
@@ -22,7 +22,7 @@ describe "redis" do
end
after
(
:each
)
do
@r
.
keys
(
'*'
).
each
{
|
k
|
@r
.
del
ete
k
}
@r
.
keys
(
'*'
).
each
{
|
k
|
@r
.
del
k
}
end
after
(
:all
)
do
...
...
@@ -30,7 +30,7 @@ describe "redis" do
end
it
'should be able to PING'
do
@r
.
ping
.
should
==
true
@r
.
ping
.
should
==
'PONG'
end
it
"should be able to GET a key"
do
...
...
@@ -62,22 +62,22 @@ describe "redis" do
@r
[
'foo'
].
should
==
nil
end
it
"should be able to SETNX
(set_unless_exists)
"
do
it
"should be able to SETNX"
do
@r
[
'foo'
]
=
'nik'
@r
[
'foo'
].
should
==
'nik'
@r
.
set
_unless_exists
'foo'
,
'bar'
@r
.
set
nx
'foo'
,
'bar'
@r
[
'foo'
].
should
==
'nik'
end
#
it
"should be able to INCR
(increment)
a key"
do
@r
.
del
ete
(
'counter'
)
it
"should be able to INCR a key"
do
@r
.
del
(
'counter'
)
@r
.
incr
(
'counter'
).
should
==
1
@r
.
incr
(
'counter'
).
should
==
2
@r
.
incr
(
'counter'
).
should
==
3
end
#
it
"should be able to DECR
(decrement)
a key"
do
@r
.
del
ete
(
'counter'
)
it
"should be able to DECR a key"
do
@r
.
del
(
'counter'
)
@r
.
incr
(
'counter'
).
should
==
1
@r
.
incr
(
'counter'
).
should
==
2
@r
.
incr
(
'counter'
).
should
==
3
...
...
@@ -85,24 +85,24 @@ describe "redis" do
@r
.
decr
(
'counter'
,
2
).
should
==
0
end
#
it
"should be able to RANDKEY
(return a random key)
"
do
it
"should be able to RANDKEY"
do
@r
.
randkey
.
should_not
be_nil
end
#
it
"should be able to RENAME a key"
do
@r
.
del
ete
'foo'
@r
.
del
ete
'bar'
@r
.
del
'foo'
@r
.
del
'bar'
@r
[
'foo'
]
=
'hi'
@r
.
rename
!
'foo'
,
'bar'
@r
.
rename
'foo'
,
'bar'
@r
[
'bar'
].
should
==
'hi'
end
#
it
"should be able to RENAMENX
(rename unless the new key already exists)
a key"
do
@r
.
del
ete
'foo'
@r
.
del
ete
'bar'
it
"should be able to RENAMENX a key"
do
@r
.
del
'foo'
@r
.
del
'bar'
@r
[
'foo'
]
=
'hi'
@r
[
'bar'
]
=
'ohai'
lambda
{
@r
.
rename
'foo'
,
'bar'
}.
should
raise_error
(
RedisRenameError
)
@r
.
renamenx
'foo'
,
'bar'
@r
[
'bar'
].
should
==
'ohai'
end
#
...
...
@@ -117,251 +117,224 @@ describe "redis" do
#
it
"should be able to EXPIRE a key"
do
@r
[
'foo'
]
=
'bar'
@r
.
expire
(
'foo'
,
1
)
@r
.
expire
'foo'
,
1
@r
[
'foo'
].
should
==
"bar"
sleep
2
@r
[
'foo'
].
should
==
nil
end
#
it
"should be able to EXISTS
(check if key exists)
"
do
it
"should be able to EXISTS"
do
@r
[
'foo'
]
=
'nik'
@r
.
key?
(
'foo'
).
should
be_true
@r
.
del
ete
'foo'
@r
.
key?
(
'foo'
).
should
be_false
@r
.
exists
(
'foo'
).
should
be_true
@r
.
del
'foo'
@r
.
exists
(
'foo'
).
should
be_false
end
#
it
"should be able to KEYS(glob for keys)"
do
@r
.
keys
(
"f*"
).
each
do
|
key
|
@r
.
delete
key
end
it
"should be able to KEYS"
do
@r
.
keys
(
"f*"
).
each
{
|
key
|
@r
.
del
key
}
@r
[
'f'
]
=
'nik'
@r
[
'fo'
]
=
'nak'
@r
[
'foo'
]
=
'qux'
@r
.
keys
(
"f*"
).
sort
.
should
==
[
'f'
,
'fo'
,
'foo'
].
sort
end
#
#
BTM - TODO
it
"should be able to check the TYPE of a key"
do
@r
[
'foo'
]
=
'nik'
@r
.
type
?
(
'foo'
).
should
==
"string"
@r
.
del
ete
'foo'
@r
.
type
?
(
'foo'
).
should
==
"none"
@r
.
type
(
'foo'
).
should
==
"string"
@r
.
del
'foo'
@r
.
type
(
'foo'
).
should
==
"none"
end
#
it
"should be able to push to the head of a list"
do
@r
.
push_head
"list"
,
'hello'
@r
.
push_head
"list"
,
42
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
pop_head
(
'list'
).
should
==
'42'
@r
.
delete
(
'list'
)
it
"should be able to push to the head of a list (LPUSH)"
do
@r
.
lpush
"list"
,
'hello'
@r
.
lpush
"list"
,
42
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
lpop
(
'list'
).
should
==
'42'
end
#
it
"should be able to push to the tail of a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
1
@r
.
delete
(
'list'
)
it
"should be able to push to the tail of a list (RPUSH)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
1
end
#
it
"should be able to pop the tail of a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
pop_tail
(
'list'
).
should
==
'goodbye'
@r
.
delete
(
'list'
)
it
"should be able to pop the tail of a list (RPOP)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
rpop
(
'list'
).
should
==
'goodbye'
end
#
it
"should be able to pop the head of a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
pop_head
(
'list'
).
should
==
'hello'
@r
.
delete
(
'list'
)
it
"should be able to pop the head of a list (LPOP)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
lpop
(
'list'
).
should
==
'hello'
end
#
it
"should be able to get the length of a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
delete
(
'list'
)
it
"should be able to get the length of a list (LLEN)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
end
#
it
"should be able to get a range of values from a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
push_tail
"list"
,
'1'
@r
.
push_tail
"list"
,
'2'
@r
.
push_tail
"list"
,
'3'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
5
@r
.
list_range
(
'list'
,
2
,
-
1
).
should
==
[
'1'
,
'2'
,
'3'
]
@r
.
delete
(
'list'
)
it
"should be able to get a range of values from a list (LRANGE)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
rpush
"list"
,
'1'
@r
.
rpush
"list"
,
'2'
@r
.
rpush
"list"
,
'3'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
5
@r
.
lrange
(
'list'
,
2
,
-
1
).
should
==
[
'1'
,
'2'
,
'3'
]
end
#
it
"should be able to trim a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
push_tail
"list"
,
'1'
@r
.
push_tail
"list"
,
'2'
@r
.
push_tail
"list"
,
'3'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
5
@r
.
list_trim
'list'
,
0
,
1
@r
.
list_length
(
'list'
).
should
==
2
@r
.
list_range
(
'list'
,
0
,
-
1
).
should
==
[
'hello'
,
'goodbye'
]
@r
.
delete
(
'list'
)
it
"should be able to trim a list (LTRIM)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
rpush
"list"
,
'1'
@r
.
rpush
"list"
,
'2'
@r
.
rpush
"list"
,
'3'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
5
@r
.
ltrim
'list'
,
0
,
1
@r
.
llen
(
'list'
).
should
==
2
@r
.
lrange
(
'list'
,
0
,
-
1
).
should
==
[
'hello'
,
'goodbye'
]
end
#
it
"should be able to get a value by indexing into a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
list_index
(
'list'
,
1
).
should
==
'goodbye'
@r
.
delete
(
'list'
)
it
"should be able to get a value by indexing into a list (LINDEX)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
lindex
(
'list'
,
1
).
should
==
'goodbye'
end
#
it
"should be able to set a value by indexing into a list"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'hello'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
list_set
(
'list'
,
1
,
'goodbye'
).
should
be_true
@r
.
list_index
(
'list'
,
1
).
should
==
'goodbye'
@r
.
delete
(
'list'
)
it
"should be able to set a value by indexing into a list (LSET)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'hello'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
lset
(
'list'
,
1
,
'goodbye'
).
should
==
'OK'
@r
.
lindex
(
'list'
,
1
).
should
==
'goodbye'
end
#
it
"should be able to remove values from a list LREM"
do
@r
.
push_tail
"list"
,
'hello'
@r
.
push_tail
"list"
,
'goodbye'
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
list_rm
(
'list'
,
1
,
'hello'
).
should
==
1
@r
.
list_range
(
'list'
,
0
,
-
1
).
should
==
[
'goodbye'
]
@r
.
delete
(
'list'
)
it
"should be able to remove values from a list (LREM)"
do
@r
.
rpush
"list"
,
'hello'
@r
.
rpush
"list"
,
'goodbye'
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
lrem
(
'list'
,
1
,
'hello'
).
should
==
1
@r
.
lrange
(
'list'
,
0
,
-
1
).
should
==
[
'goodbye'
]
end
#
it
"should be able add members to a set"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
type?
(
'set'
).
should
==
"set"
@r
.
set_count
(
'set'
).
should
==
2
@r
.
set_members
(
'set'
).
sort
.
should
==
[
'key1'
,
'key2'
].
sort
@r
.
delete
(
'set'
)
it
"should be able add members to a set (SADD)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
type
(
'set'
).
should
==
"set"
@r
.
scard
(
'set'
).
should
==
2
@r
.
smembers
(
'set'
).
sort
.
should
==
[
'key1'
,
'key2'
].
sort
end
#
it
"should be able delete members to a set"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
type?
(
'set'
).
should
==
"set"
@r
.
set_count
(
'set'
).
should
==
2
@r
.
set_members
(
'set'
).
should
==
Set
.
new
([
'key1'
,
'key2'
])
@r
.
set_delete
(
'set'
,
'key1'
)
@r
.
set_count
(
'set'
).
should
==
1
@r
.
set_members
(
'set'
).
should
==
Set
.
new
([
'key2'
])
@r
.
delete
(
'set'
)
it
"should be able delete members to a set (SREM)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
type
(
'set'
).
should
==
"set"
@r
.
scard
(
'set'
).
should
==
2
@r
.
smembers
(
'set'
).
sort
.
should
==
[
'key1'
,
'key2'
].
sort
@r
.
srem
(
'set'
,
'key1'
)
@r
.
scard
(
'set'
).
should
==
1
@r
.
smembers
(
'set'
).
should
==
[
'key2'
]
end
#
it
"should be able count the members of a set"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
type?
(
'set'
).
should
==
"set"
@r
.
set_count
(
'set'
).
should
==
2
@r
.
delete
(
'set'
)
it
"should be able count the members of a set (SCARD)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
type
(
'set'
).
should
==
"set"
@r
.
scard
(
'set'
).
should
==
2
end
#
it
"should be able test for set membership"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
type?
(
'set'
).
should
==
"set"
@r
.
set_count
(
'set'
).
should
==
2
@r
.
set_member?
(
'set'
,
'key1'
).
should
be_true
@r
.
set_member?
(
'set'
,
'key2'
).
should
be_true
@r
.
set_member?
(
'set'
,
'notthere'
).
should
be_false
@r
.
delete
(
'set'
)
it
"should be able test for set membership (SISMEMBER)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
type
(
'set'
).
should
==
"set"
@r
.
scard
(
'set'
).
should
==
2
@r
.
sismember
(
'set'
,
'key1'
).
should
be_true
@r
.
sismember
(
'set'
,
'key2'
).
should
be_true
@r
.
sismember
(
'set'
,
'notthere'
).
should
be_false
end
#
it
"should be able to do set intersection"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
set_add
"set2"
,
'key2'
@r
.
set_intersect
(
'set'
,
'set2'
).
should
==
Set
.
new
([
'key2'
])
@r
.
delete
(
'set'
)
it
"should be able to do set intersection (SINTER)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
sadd
"set2"
,
'key2'
@r
.
sinter
(
'set'
,
'set2'
).
should
==
[
'key2'
]
end
#
it
"should be able to do set intersection and store the results in a key"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
set_add
"set2"
,
'key2'
@r
.
set_inter_store
(
'newone'
,
'set'
,
'set2'
).
should
==
'OK'
@r
.
set_members
(
'newone'
).
should
==
Set
.
new
([
'key2'
])
@r
.
delete
(
'set'
)
@r
.
delete
(
'set2'
)
it
"should be able to do set intersection and store the results in a key (SINTERSTORE)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
sadd
"set2"
,
'key2'
@r
.
sinterstore
(
'newone'
,
'set'
,
'set2'
).
should
==
1
@r
.
smembers
(
'newone'
).
should
==
[
'key2'
]
end
#
it
"should be able to do set union"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
set_add
"set2"
,
'key2'
@r
.
set_add
"set2"
,
'key3'
@r
.
set_union
(
'set'
,
'set2'
).
should
==
Set
.
new
([
'key1'
,
'key2'
,
'key3'
])
@r
.
delete
(
'set'
)
@r
.
delete
(
'set2'
)
it
"should be able to do set union (SUNION)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
sadd
"set2"
,
'key2'
@r
.
sadd
"set2"
,
'key3'
@r
.
sunion
(
'set'
,
'set2'
).
sort
.
should
==
[
'key1'
,
'key2'
,
'key3'
].
sort
end
#
it
"should be able to do set union and store the results in a key"
do
@r
.
set_add
"set"
,
'key1'
@r
.
set_add
"set"
,
'key2'
@r
.
set_add
"set2"
,
'key2'
@r
.
set_add
"set2"
,
'key3'
@r
.
set_union_store
(
'newone'
,
'set'
,
'set2'
).
should
==
'OK'
@r
.
set_members
(
'newone'
).
should
==
Set
.
new
([
'key1'
,
'key2'
,
'key3'
])
@r
.
delete
(
'set'
)
@r
.
delete
(
'set2'
)
it
"should be able to do set union and store the results in a key (SUNIONSTORE)"
do
@r
.
sadd
"set"
,
'key1'
@r
.
sadd
"set"
,
'key2'
@r
.
sadd
"set2"
,
'key2'
@r
.
sadd
"set2"
,
'key3'
@r
.
sunionstore
(
'newone'
,
'set'
,
'set2'
).
should
==
3
@r
.
smembers
(
'newone'
).
sort
.
should
==
[
'key1'
,
'key2'
,
'key3'
].
sort
end
#
it
"should be able to do set difference"
do
@r
.
set_add
"set"
,
'a'
@r
.
set_add
"set"
,
'b'
@r
.
set_add
"set2"
,
'b'
@r
.
set_add
"set2"
,
'c'
@r
.
set_diff
(
'set'
,
'set2'
).
should
==
Set
.
new
([
'a'
])
@r
.
delete
(
'set'
)
@r
.
delete
(
'set2'
)
it
"should be able to do set difference (SDIFF)"
do
@r
.
sadd
"set"
,
'a'
@r
.
sadd
"set"
,
'b'
@r
.
sadd
"set2"
,
'b'
@r
.
sadd
"set2"
,
'c'
@r
.
sdiff
(
'set'
,
'set2'
).
should
==
[
'a'
]
end
#
it
"should be able to do set difference and store the results in a key"
do
@r
.
set_add
"set"
,
'a'
@r
.
set_add
"set"
,
'b'
@r
.
set_add
"set2"
,
'b'
@r
.
set_add
"set2"
,
'c'
@r
.
set_diff_store
(
'newone'
,
'set'
,
'set2'
)
@r
.
set_members
(
'newone'
).
should
==
Set
.
new
([
'a'
])
@r
.
delete
(
'set'
)
@r
.
delete
(
'set2'
)
it
"should be able to do set difference and store the results in a key (SDIFFSTORE)"
do
@r
.
sadd
"set"
,
'a'
@r
.
sadd
"set"
,
'b'
@r
.
sadd
"set2"
,
'b'
@r
.
sadd
"set2"
,
'c'
@r
.
sdiffstore
(
'newone'
,
'set'
,
'set2'
)
@r
.
smembers
(
'newone'
).
should
==
[
'a'
]
end
#
it
"should be able move elements from one set to another"
do
@r
.
s
et_
add
'set1'
,
'a'
@r
.
s
et_
add
'set1'
,
'b'
@r
.
s
et_
add
'set2'
,
'x'
@r
.
s
et_move
(
'set1'
,
'set2'
,
'a'
).
should
==
true
@r
.
s
et_member?
(
'set2'
,
'a'
).
should
==
true
it
"should be able move elements from one set to another
(SMOVE)
"
do
@r
.
sadd
'set1'
,
'a'
@r
.
sadd
'set1'
,
'b'
@r
.
sadd
'set2'
,
'x'
@r
.
s
move
(
'set1'
,
'set2'
,
'a'
).
should
be_true
@r
.
s
ismember
(
'set2'
,
'a'
).
should
be_
true
@r
.
delete
(
'set1'
)
end
#
it
"should be able to do crazy SORT queries"
do
@r
[
'dog_1'
]
=
'louie'
@r
.
push_tail
'dogs'
,
1
@r
.
rpush
'dogs'
,
1
@r
[
'dog_2'
]
=
'lucy'
@r
.
push_tail
'dogs'
,
2
@r
.
rpush
'dogs'
,
2
@r
[
'dog_3'
]
=
'max'
@r
.
push_tail
'dogs'
,
3
@r
.
rpush
'dogs'
,
3
@r
[
'dog_4'
]
=
'taj'
@r
.
push_tail
'dogs'
,
4
@r
.
rpush
'dogs'
,
4
@r
.
sort
(
'dogs'
,
:get
=>
'dog_*'
,
:limit
=>
[
0
,
1
]).
should
==
[
'louie'
]
@r
.
sort
(
'dogs'
,
:get
=>
'dog_*'
,
:limit
=>
[
0
,
1
],
:order
=>
'desc alpha'
).
should
==
[
'taj'
]
end
...
...
@@ -369,16 +342,16 @@ describe "redis" do
it
"should be able to handle array of :get using SORT"
do
@r
[
'dog:1:name'
]
=
'louie'
@r
[
'dog:1:breed'
]
=
'mutt'
@r
.
push_tail
'dogs'
,
1
@r
.
rpush
'dogs'
,
1
@r
[
'dog:2:name'
]
=
'lucy'
@r
[
'dog:2:breed'
]
=
'poodle'
@r
.
push_tail
'dogs'
,
2
@r
.
rpush
'dogs'
,
2
@r
[
'dog:3:name'
]
=
'max'
@r
[
'dog:3:breed'
]
=
'hound'
@r
.
push_tail
'dogs'
,
3
@r
.
rpush
'dogs'
,
3
@r
[
'dog:4:name'
]
=
'taj'
@r
[
'dog:4:breed'
]
=
'terrier'
@r
.
push_tail
'dogs'
,
4
@r
.
rpush
'dogs'
,
4
@r
.
sort
(
'dogs'
,
:get
=>
[
'dog:*:name'
,
'dog:*:breed'
],
:limit
=>
[
0
,
1
]).
should
==
[
'louie'
,
'mutt'
]
@r
.
sort
(
'dogs'
,
:get
=>
[
'dog:*:name'
,
'dog:*:breed'
],
:limit
=>
[
0
,
1
],
:order
=>
'desc alpha'
).
should
==
[
'taj'
,
'terrier'
]
end
...
...
@@ -392,13 +365,13 @@ describe "redis" do
it
"should be able to flush the database"
do
@r
[
'key1'
]
=
'keyone'
@r
[
'key2'
]
=
'keytwo'
@r
.
keys
(
'*'
).
sort
.
should
==
[
'foo'
,
'key1'
,
'key2'
]
#foo from before
@r
.
flush
_
db
@r
.
keys
(
'*'
).
sort
.
should
==
[
'foo'
,
'key1'
,
'key2'
]
.
sort
#foo from before
@r
.
flushdb
@r
.
keys
(
'*'
).
should
==
[]
end
#
it
"should be able to provide the last save time"
do
savetime
=
@r
.
last
_
save
it
"should be able to provide the last save time
(LASTSAVE)
"
do
savetime
=
@r
.
lastsave
Time
.
at
(
savetime
).
class
.
should
==
Time
Time
.
at
(
savetime
).
should
<=
Time
.
now
end
...
...
@@ -411,13 +384,12 @@ describe "redis" do
end
it
"should bgsave"
do
lambda
{
@r
.
bgsave
}.
should_not
raise_error
(
RedisError
)
@r
.
bgsave
.
should
==
'OK'
end
it
"should handle multiple servers"
do
require
'dist_redis'
@r
=
DistRedis
.
new
(
'localhost:6379'
,
'127.0.0.1:6379'
)
@r
.
select_db
(
15
)
# use database 15 for testing so we dont accidentally step on you real data
@r
=
DistRedis
.
new
(
:hosts
=>
[
'localhost:6379'
,
'127.0.0.1:6379'
],
:db
=>
15
)
100
.
times
do
|
idx
|
@r
[
idx
]
=
"foo
#{
idx
}
"
...
...
@@ -430,16 +402,13 @@ describe "redis" do
it
"should be able to pipeline writes"
do
@r
.
pipelined
do
|
pipeline
|
pipeline
.
push_head
"list"
,
"hello"
pipeline
.
push_head
"list"
,
42
pipeline
.
lpush
'list'
,
"hello"
pipeline
.
lpush
'list'
,
42
end
@r
.
type?
(
'list'
).
should
==
"list"
@r
.
list_length
(
'list'
).
should
==
2
@r
.
pop_head
(
'list'
).
should
==
'42'
@r
.
delete
(
'list'
)
@r
.
type
(
'list'
).
should
==
"list"
@r
.
llen
(
'list'
).
should
==
2
@r
.
lpop
(
'list'
).
should
==
'42'
end
it
"should select db on connection"
it
"should re-select db on reconnection"
end
client-libraries/update-ruby-client.sh
浏览文件 @
0df1ead7
...
...
@@ -2,7 +2,8 @@
rm
-rf
temp
mkdir
temp
cd
temp
git clone git://github.com/ezmobius/redis-rb.git
#git clone git://github.com/ezmobius/redis-rb.git
git clone git://github.com/jodosha/redis-rb.git
cd
redis-rb
rm
-rf
.git
cd
..
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录