$Redis::Client::Role::URP::VERSION
=
'0.015'
;
our
@CARP_NOT
= (
'Redis::Client'
);
my
$CRLF
=
"\x0D\x0A"
;
has
'_sock'
=> (
is
=>
'rw'
,
isa
=>
'IO::Socket'
,
init_arg
=>
undef
,
lazy_build
=> 1,
predicate
=>
'_have_sock'
,
clearer
=>
'_clear_sock'
);
requires
'host'
;
requires
'port'
;
sub
_build__sock {
my
$self
=
shift
;
my
$sock
= IO::Socket::INET->new(
PeerAddr
=>
$self
->host,
PeerPort
=>
$self
->port,
Proto
=>
'tcp'
,
) or
die
sprintf
q{Can't connect to Redis host at %s:%s: %s}
,
$self
->host,
$self
->port, $@;
return
$sock
;
}
sub
send_command {
my
$self
=
shift
;
my
(
$cmd
,
@args
) =
@_
;
my
$sock
=
$self
->_sock;
my
@cmd
= ();
(
$cmd
=~ /\s/) ? (
@cmd
=
split
(/\s/,
$cmd
)) : (
@cmd
= (
$cmd
));
my
$cmd_block
=
$self
->_build_urp(
@cmd
,
@args
);
$sock
->
send
(
$cmd_block
);
return
$self
->_get_response;
}
sub
_build_urp {
my
$self
=
shift
;
my
@items
=
@_
;
my
$length
=
@_
;
my
$block
=
sprintf
'*%s%s'
,
$length
,
$CRLF
;
foreach
my
$line
(
@items
) {
$block
.=
sprintf
'$%s%s'
,
length
$line
,
$CRLF
;
$block
.=
$line
.
$CRLF
;
}
return
$block
;
}
sub
_get_response {
my
$self
=
shift
;
my
$sock
=
$self
->_sock;
my
%msg_types
= (
'+'
=>
'_read_single_line'
,
'-'
=>
'_read_single_line'
,
':'
=>
'_read_single_line'
,
'$'
=>
'_read_bulk_reply'
,
'*'
=>
'_read_multi_bulk_reply'
);
my
$buf
;
$sock
->
read
(
$buf
, 1 );
die
"Can't read from socket"
unless
$buf
;
die
"Can't understand Redis message type [$buf]"
unless
exists
$msg_types
{
$buf
};
my
$meth
=
$msg_types
{
$buf
};
if
(
$buf
eq
'-'
) {
my
$err
=
$self
->
$meth
;
$err
=~ s/ERR\s/Redis: /;
$self
->_sock(
$self
->_build__sock );
croak
$err
;
}
return
$self
->
$meth
;
}
sub
_read_multi_bulk_reply {
my
$self
=
shift
;
my
$sock
=
$self
->_sock;
local
$/ =
$CRLF
;
my
$parts
=
readline
$sock
;
chomp
$parts
;
return
if
$parts
== 0;
my
@results
;
foreach
my
$part
( 1 ..
$parts
) {
push
@results
,
$self
->_get_response;
}
return
@results
;
}
sub
_read_bulk_reply {
my
$self
=
shift
;
my
$sock
=
$self
->_sock;
local
$/ =
$CRLF
;
my
$length
=
readline
$sock
;
chomp
$length
;
return
undef
if
$length
== -1;
my
$buf
;
$sock
->
read
(
$buf
,
$length
);
readline
$sock
;
return
$buf
;
}
sub
_read_single_line {
my
$self
=
shift
;
my
$sock
=
$self
->_sock;
local
$/ =
$CRLF
;
my
$val
=
readline
$sock
;
chomp
$val
;
return
$val
;
}
1;