The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

RedisDB - Perl extension to access redis database

SYNOPSIS

    use RedisDB;

    my $redis = RedisDB->new(host => 'localhost', port => 6379);
    $redis->set($key, $value);
    my $value = $redis->get($key);

DESCRIPTION

This module provides interface to access redis database. It transparently handles disconnects and forks. It supports pipelining mode.

METHODS

$class->new(%options)

Creates new RedisDB object. The following options are allowed:

host

domain name of the host running redis server. Default: "localhost"

port

port to connect. Default: 6379

path

you can connect to redis using UNIX socket. In this case instead of host and port you should specify path.

timeout

IO timeout. With this option set, if IO operation will take more than specified number of seconds module will croak. Note, that some OSes don't support SO_RCVTIMEO, and SO_SNDTIMEO socket options, in this case timeout will not work.

lazy

by default new establishes connection to the server. If this parameter is set, then connection will be established when you will send command to the server.

$self->execute($command, @arguments)

send command to the server and return server reply. It throws exception if server returns error. It may be more convenient to use instead of this method wrapper named after the redis command. E.g.:

    $redis->execute('set', key => 'value');
    # is the same as
    $redis->set(key => 'value');

See "SUPPORTED REDIS COMMANDS" section for the full list of defined aliases.

Note, that you can't use execute if you have sent some commands in pipelining mode and haven't yet got all replies.

$self->send_command($command[, @arguments])

send command to the server. Returns true if command was successfully sent, or dies if error occured. Note, that it doesn't return server reply, you should retrieve reply using get_reply method.

$self->send_command_cb($command[, @arguments][, \&callback])

send command to the server, invoke specified callback on reply. Callback invoked with 2 arguments: RedisDB object, and reply from the server. If server return error reply will be RedisDB::Error object, you can get description of error using this object in string context. If callback is not specified reply will be discarded. Note, that RedisDB doesn't run any background threads, so it will not receive reply and invoke callback unless you call some of it's methods which check if there's reply from the server, like send_command, send_command_cb, reply_ready, get_reply, or get_all_replies.

$self->reply_ready

This method may be used in pipelining mode to check if there are some replies already received from server. Returns number of replies available for reading.

$self->get_reply

receive reply from the server. Method croaks if server returns error reply.

$self->get_all_replies

Wait replies to all sent commands and return them as a list.

$self->replies_to_fetch

Return number of commands sent to server replies to which wasn't yet retrieved with get_reply or get_all_replies.

$self->version

Return version of the server client is connected to. Version is returned as floating point number represented the same way as the perl versions. E.g. for redis 2.1.12 it will return 2.001012.

SUPPORTED REDIS COMMANDS

Usually, instead of using execute method, you can just use methods with names matching names of the redis commands. The following methods are defined as wrappers around execute: append, auth, bgrewriteaof, bgsave, blpop, brpop, brpoplpush, config_get, config_set, config_resetstat, dbsize, debug_object, debug_segfault, decr, decrby, del, echo, exists, expire, expireat, flushall, flushdb, get, getbit, getrange, getset, hdel, hexists, hget, hgetall, hincrby, hkeys, hlen, hmget, hmset, hset, hsetnx, hvals, incr, incrby, keys, lastsave, lindex, linsert, llen, lpop, lpush, lpushx, lrange, lrem, lset, ltrim, mget, move, mset, msetnx, persist, ping, publish, quit, randomkey, rename, renamenx, rpop, rpoplpush, rpush, rpushx, sadd, save, scard, sdiff, sdiffstore, select, set, setbit, setex, setnx, setrange, sinter, sinterstore, sismember, slaveof, smembers, smove, sort, spop, srandmember, srem, strlen, sunion, sunionstore, sync, ttl, type, unwatch, watch, zadd, zcard, zcount, zincrby, zinterstore, zrange, zrangebyscore, zrank, zrem, zremrangebyrank, zremrangebyscore, zrevrange, zrevrangebyscore, zrevrank, zscore, zunionstore

See description of all commands in redis documentation at http://redis.io/commands.

The following commands implement some additional postprocessing of results:

$self->info

Return information and statistics about server. Redis returns information in form of field:value, info method parses result and returns it as hash reference.

$self->shutdown

Shuts redis server down. Returns undef, as server doesn't send answer. Croaks in case of error.

HANDLING OF SERVER DISCONNECTS

Redis server may close connection if it was idle for some time, also connection may be closed in case redis-server was restarted. RedisDB restores connection to the server but only if no data was lost as result of disconnect. E.g. if client was idle for some time and redis server closed connection, it will be transparently restored on sending next command. If you send a command and server closed connection without sending complete reply, connection will not be restored and module will throw exception. Also module will throw exception if connection will be closed in the middle of transaction or while you're in subscription loop.

PIPELINING SUPPORT

You can send commands in pipelining mode. In this case you sending multiple commands to the server without waiting for replies. You can use send_command and send_command_cb methods to send multiple commands to the server. In case of send_command reply_ready method may be used to check if some replies are already received, and get_reply method may be used to fetch received reply. In case of send_command_cb redis will invoke specified callback when it receive reply. Also if you not interested in reply you can omit callback, then reply will be dropped. Note, that RedisDB checks for replies only when you calling some of its methods, so the following loop will never exit:

    my $reply;
    $redis->send_command_cb("PING", sub { $reply = $_[1] });
    sleep 1 while not $reply;

because redis will never receive reply and invoke callback.

Note also, that you can't use execute method (or wrappers around it, like get or set) while in pipeline mode, you must receive replies on all pipelined commands first.

SUBSCRIPTIONS SUPPORT

RedisDB supports subscriptions to redis channels. In subscription mode you can subscribe to some channels and receive all messages sent to these channels. Every time RedisDB receives message for the channel it invokes callback provided by user. User can specify different callbacks for different channels. When in subscription mode you can subscribe to additional channels, or unsubscribe from channels you subscribed to, but you can't use any other redis commands like set, get, etc. Here's example of running in subscription mode:

    my $message_cb = sub {
        my ($redis, $channel, $pattern, $message) = @_;
        print "$channel: $message\n";
    };
    
    my $control_cb = sub {
        my ($redis, $channel, $pattern, $message) = @_;
        if ($channel eq 'control.quit') {
            $redis->unsubscribe;
            $redis->punsubscribe;
        }
        elsif ($channel eq 'control.subscribe') {
            $redis->subscribe($message);
        }
    };
    
    subscription_loop(
        subscribe => [ 'news',  ],
        psubscribe => [ 'control.*' => $control_cb ],
        default_callback => $message_cb,
    );

subscription_loop will subscribe you to news channel and control.* channels. It will call specified callbacks every time new message received. You can subscribe to additional channels sending their names to control.subscribe channel. You can unsubscribe from all channels by sending message to control.quit channel. Every callback receives four arguments: RedisDB object, channel for which message was received, pattern if you subscribed to this channel using psubscribe method, and message itself.

You can publish messages into channels using publish method. This method should be called when you in normal mode, and can't be used while you're in subscription mode.

Following methods can be used in subscribtion mode:

$self->subscription_loop(%parameters)

Enter into subscription mode. Function subscribes you to specified channels, waits for messages, and invokes callbacks for every received message. Function returns after you unsubscribed from all channels. It accepts following parameters:

default_callback

reference to the default callback. This callback is invoked for the message if you didn't specify other callback for the channel this message comes from.

subscribe

array reference. Contains list of channels you want to subscribe. Channel name may be optionally followed by reference to callback function for this channel. E.g.:

    [ 'news', 'messages', 'errors' => \&error_cb, 'other' ]

channels "news", "messages", and "other" will use default callback, but for "errors" channel error_cb function will be used.

psubscribe

same as subscribe, but you specify patterns for channels' names.

All parameters are optional, but you must subscribe at least to one channel. Also if default_callback is not specified, you have to explicitely specify callback for every channel you're going to subscribe.

$self->subscribe($channel[, $callback])

Subscribe to additional $channel. If $callback is not specified, default callback will be used.

$self->psubscribe($pattern[, $callback])

Subscribe to additional channels matching $pattern. If $callback is not specified, default callback will be used.

$self->unsubscribe([@channels])

Unsubscribe from the listed @channels. If no channels specified, unsubscribe from all channels.

$self->punsubscribe([@patterns])

Unsubscribe from the listed @patterns. If no patterns specified, unsubscribe from all channels to which you subscribed using psubscribe.

$self->subscribed

Return list of channels to which you have subscribed using subscribe

$self->psubscribed

Return list of channels to which you have subscribed using psubscribe

TRANSACTIONS SUPPORT

Transactions allow you execute a sequence of commands in a single step. In order to start transaction you should use method multi. After you entered transaction all commands you issue are queued, but not executed till you call exec method. Tipically these commands return string "QUEUED" as result, but if there's an error in e.g. number of arguments they may croak. When you calling exec all queued commands are executed and exec returns list of results for every command in transaction. If any command failed exec will croak. If instead of exec you will call discard, all scheduled commands will be canceled.

You can set some keys as watched. If any whatched key will be changed by another client before you call exec, transaction will be discarded and exec will return false value.

$self->multi

Enter transaction. After this and till exec or discard will be called, all commands will be queued but not executed.

$self->exec

Execute all queued commands and finish transaction. Returns list of results for every command. May croak if some command failed. Also unwatches all keys. If some of the watched keys was changed by other client, transaction will be canceled and exec will return false.

$self->discard

Discard all queued commands without executing them and unwatch all keys.

SEE ALSO

Redis, Redis::hiredis, AnyEvent::Redis

WHY ANOTHER ONE

I was in need of a client for redis database. AnyEvent::Redis didn't suite me as it requires event loop, and it didn't fit into existing code. Problem with Redis is that it doesn't (at the time I write this) reconnect to the server if connection was closed after timeout or as result or server restart, and it doesn't support pipelining. After analizing what I need to change in Redis in order to get all I want (see TODO), I decided that it will be simplier to write new module from scratch. This also solves the problem of backward compatibility. Pedro Melo, maintainer of Redis have plans to implement some of these features too.

BUGS

Please report any bugs or feature requests via GitHub bug tracker at http://github.com/trinitum/RedisDB/issues.

Known bugs are:

Timeout support is OS dependent. If OS doesn't support SO_SNDTIMEO and SO_RCVTIMEO options timeouts will not work.

ACKNOWLEDGEMENTS

Thanks to Sanko Robinson and FunkyMonk for help with porting this module on Windows.

AUTHOR

Pavel Shaydo, <zwon at cpan.org>

LICENSE AND COPYRIGHT

Copyright 2011 Pavel Shaydo.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.