Hey guys, While looking at FileStorable cache issue with our OTRS cluster, I realized it should not be so hard to write Redis cache backend.
Attached is module to put in Kernel/System/Cache/ - install dependency: apt-get install libredis-perl - Set up Redis server and point to it in Config.pm: $Self->{'RedisServer'} = '10.10.10.10:6379'; - Select new backend in Cache::Module SysConfig Does not make sense for one server, but if you are on NFS makes so much big difference. Should be fairly easy to port to Memcache. Any comments ? -- Artis Caune Everything should be made as simple as possible, but not simpler.
package Kernel::System::Cache::RedisStorable; use strict; use Digest::MD5 qw(md5_hex); use Try::Tiny; use Redis; use vars qw(@ISA $VERSION); $VERSION = qw($Revision: 1.0 $) [1]; sub new { my ( $Type, %Param ) = @_; my $Self = {}; bless( $Self, $Type ); # check needed objects for (qw(ConfigObject LogObject MainObject EncodeObject)) { $Self->{$_} = $Param{$_} || die "Got no $_!"; } if (!$Self->{ConfigObject}->{redis}) { my $RedisServer = $Self->{ConfigObject}->Get('RedisServer'); my $r; try { $r = Redis->new(server => $RedisServer); } catch { return $Self; }; $Self->{ConfigObject}->{redis} = $r; } return $Self; } sub Set { my ( $Self, %Param ) = @_; return if !$Self->{ConfigObject}->{redis}; # check needed stuff for my $Needed (qw(Type Key Value TTL)) { if ( !defined $Param{$Needed} ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Need $Needed!" ); return; } } my $Dump = Storable::nfreeze( { TTL => time() + $Param{TTL}, Value => $Param{Value}, } ); my $Filename = $Self->{EncodeObject}->EncodeOutput($Param{Key}); my $Key = $Param{Type} . '/' . md5_hex($Filename); my $Value = $Self->{EncodeObject}->EncodeOutput($Dump); try { $Self->{ConfigObject}->{redis}->set($Key => $Value); $Self->{ConfigObject}->{redis}->expire($Key => $Param{TTL}); } catch { undef $Self->{ConfigObject}->{redis}; return; }; return 1; } sub Get { my ( $Self, %Param ) = @_; my $Content; return if !$Self->{ConfigObject}->{redis}; # check needed stuff for my $Needed (qw(Type Key)) { if ( !defined $Param{$Needed} ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Need $Needed!" ); return; } } my $Filename = $Self->{EncodeObject}->EncodeOutput($Param{Key}); my $Key = $Param{Type} . '/' . md5_hex($Filename); try { $Content = $Self->{ConfigObject}->{redis}->get($Key); } catch { undef $Self->{ConfigObject}->{redis}; return; }; # check if cache exists return if !$Content; # read data structure back from file dump, use block eval for safety reasons my $Storage = eval { Storable::thaw( $Content ) }; if ( ref $Storage ne 'HASH' ) { $Self->Delete(%Param); return; } return $Storage->{Value}; } sub Delete { my ( $Self, %Param ) = @_; return if !$Self->{ConfigObject}->{redis}; # check needed stuff for my $Needed (qw(Type Key)) { if ( !defined $Param{$Needed} ) { $Self->{LogObject}->Log( Priority => 'error', Message => "Need $Needed!" ); return; } } my $Filename = $Self->{EncodeObject}->EncodeOutput($Param{Key}); my $Key = $Param{Type} . '/' . md5_hex($Filename); try { $Self->{ConfigObject}->{redis}->del($Key); } catch { undef $Self->{ConfigObject}->{redis}; return; }; return 1; } sub CleanUp { my ( $Self, %Param ) = @_; return if !$Self->{ConfigObject}->{redis}; if ( $Param{Expired} ) { return 1; } if ( !$Param{Type} ) { try { $Self->{ConfigObject}->{redis}->flushdb(); } catch { undef $Self->{ConfigObject}->{redis}; return; }; return 1; } my @keys; try { @keys = $Self->{ConfigObject}->{redis}->keys( $Param{Type} . '/*' ); foreach (@keys) { $Self->{ConfigObject}->{redis}->del($_); } } catch { undef $Self->{ConfigObject}->{redis}; return; }; return 1; } 1;
--------------------------------------------------------------------- OTRS mailing list: otrs - Webpage: http://otrs.org/ Archive: http://lists.otrs.org/pipermail/otrs To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/otrs