p5-RedisDB / RedisDB

Perl extension to access Redis
22 stars 11 forks source link

Soft-Error on connection-issues #10

Closed senfomat closed 11 years ago

senfomat commented 11 years ago

Is there a possibility to get a more soft error from RedisDB on connection-issues? The current situation simply exits the running script via croak. Which in my case is problematic, because the script has to return data even without a working redis-connection.

trinitum commented 11 years ago

You can wrap call to redis into eval, or use Try::Tiny. If it is not suitable for you, can you provide an example of the desired behaviour?

senfomat commented 11 years ago

Its a little based on the error-handling of the DBI-Module.

The "err"- and "errstr"-Attributes should be cleared on every request, so it gives only errors on the last action.

Example:

use RedisDB;

my $redis = RedisDB->new(
                        path      => '/path/to/redis.sock',
                        softerror => 1,
                );

LINE:
while(my $key = <>)
{
   chomp($key);
   my $value = $redis->get("whatever::$key");
   if (defined $redis->err)
   {
      # Log an Error or a warning, warn() only as example
      warn($redis->errstr);

      # give something like a temporary error to the application
      # ...

      next LINE;
   }

   # do something with $value
   # ...
}

In the current implementation I have to wrap every call to redis in Try-Tiny or eval, becaus on every error the script exits right away. The wrapping is more complicated when doing multipe requests, I think. So an in-module-solution would be very nice.

Thank you.

trinitum commented 11 years ago

Ok, but then after every call to redis you will have to check the error, which is not that much better.

Give me some time, I need to think about it and look how I can implement it.

trinitum commented 11 years ago

Sorry for the long silence. I added raise_error parameter which is true by default. If you set it to false, get_reply, execute, and synchronous command wrappers will return RedisDB::Error object instead of dying when server returns an error. E.g.:

$redis = RedisDB->new(raise_error => 0);
...;
$res = $redis->get('key');
if (ref $res eq 'RedisDB::Error') {
    # handle error
    ...;
}

This is in line with how callbacks handle errors. I also think about improving connect/reconnect errors handling, perhaps I will add some callbacks for this. Cases when data was lost as a result of disconnect or invalid data came from the server will still throw exceptions and I don't have plans to do anything about it. If you really want to ignore such errors I would recommend you to subclass RedisDB and wrap execute method into eval block using Class::Method::Modifiers.

trinitum commented 11 years ago

I uploaded RedisDB 2.10 to CPAN, it comes with raise_error option. I also added on_connect_error callback which may help in case of connection problems.