fixing zebraqueue daemon for delete operation part two

Signed-off-by: Joshua Ferraro <jmf@liblime.com>
This commit is contained in:
Joshua Ferraro 2008-02-12 23:30:26 -05:00
parent 6a5b9194d5
commit fcffbe744e

View file

@ -19,7 +19,6 @@ use C4::AuthoritiesMarc;
use XML::Simple; use XML::Simple;
use utf8; use utf8;
my $dbh=C4::Context->dbh; my $dbh=C4::Context->dbh;
my $ident = "Koha Zebraqueue "; my $ident = "Koha Zebraqueue ";
@ -46,103 +45,132 @@ sub handler_sleep {
# can be used to slow down loop execution if needed # can be used to slow down loop execution if needed
my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ];
use Time::HiRes qw (sleep);
sleep 1; Time::HiRes::sleep(0.01);
#sleep 1;
$kernel->yield('status_check'); $kernel->yield('status_check');
} }
sub handler_check { sub handler_check {
# check if we need to do anything, at the moment just checks the zebraqueue, it could check other things too # check if we need to do anything, at the moment just checks the zebraqueue, it could check other things too
my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ];
my $dbh=C4::Context->dbh; my $dbh=C4::Context->dbh;
my $sth = $dbh->prepare("SELECT count(*) AS opcount FROM zebraqueue WHERE done = 0"); my $sth = $dbh->prepare("SELECT count(*) AS opcount FROM zebraqueue WHERE done = 0");
$sth->execute; $sth->execute;
my $data = $sth->fetchrow_hashref(); my $data = $sth->fetchrow_hashref();
if ($data->{'opcount'} > 0){ if ($data->{'opcount'} > 0){
Unix::Syslog::syslog LOG_INFO, "$data->{'opcount'} operations waiting to be run\n"; Unix::Syslog::syslog LOG_INFO, "$data->{'opcount'} operations waiting to be run\n";
$sth->finish(); $sth->finish();
$kernel->yield('do_ops'); $kernel->yield('do_ops');
} }
else { else {
$sth->finish(); $sth->finish();
$kernel->yield('sleep'); $kernel->yield('sleep');
} }
} }
sub zebraop { sub zebraop {
# execute operations waiting in the zebraqueue # execute operations waiting in the zebraqueue
my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ]; my ( $kernel, $heap, $session ) = @_[ KERNEL, HEAP, SESSION ];
my $dbh=C4::Context->dbh; my $dbh=C4::Context->dbh;
my $readsth=$dbh->prepare("SELECT id,biblio_auth_number,operation,server FROM zebraqueue WHERE done=0"); my $readsth=$dbh->prepare("SELECT id,biblio_auth_number,operation,server FROM zebraqueue WHERE done=0");
$readsth->execute(); $readsth->execute();
Unix::Syslog::syslog LOG_INFO, "Executing zebra operations\n"; Unix::Syslog::syslog LOG_INFO, "Executing zebra operations\n";
while (my $data = $readsth->fetchrow_hashref()){ while (my $data = $readsth->fetchrow_hashref()){
eval { warn "Inside while loop" if $debug;
my $ok = 0; eval {
if ($data->{'operation'} =~ /delete/i ){ my $ok = 0;
# 1st read the record in zebra, we have to get it from zebra as its no longer in the db if ($data->{'operation'} =~ /delete/i ){
my $Zconn=C4::Context->Zconn($data->{'server'}, 0, 1,'','xml'); eval {
my $query = $Zconn->search_pqf( '@attr 1=Local-Number '.$data->{'biblio_auth_number'});
# then, delete the record warn "Searching for record to delete" if $debug;
$ok=zebrado($query->record(0)->render(),$data->{'operation'},$data->{'server'},$data->{'biblio_auth_number'}); # 1st read the record in zebra, we have to get it from zebra as its no longer in the db
} my $Zconn=C4::Context->Zconn($data->{'server'}, 0, 1,'','xml');
else { my $query = $Zconn->search_pqf( '@attr 1=Local-number '.$data->{'biblio_auth_number'});
# it is an update
# get the XML # then, delete the record
my $marcxml; warn "Deleting record" if $debug;
if ($data->{'server'} eq "biblioserver") { $ok=zebrado($query->record(0)->render(),$data->{'operation'},$data->{'server'},$data->{'biblio_auth_number'});
my $marc = GetMarcBiblio($data->{'biblio_auth_number'}); };
$marcxml = $marc->as_xml_record() if $marc;
} if ($@) {
elsif ($data->{'server'} eq "authorityserver") { # caught a ZOOM::Exception
$marcxml =C4::AuthoritiesMarc::GetAuthorityXML($data->{'biblio_auth_number'}); my $error =
} $@->message() . " ("
# check it's XML, just in case . $@->code() . ") "
eval { . $@->addinfo() . " "
my $hashed=XMLin($marcxml); . $@->diagset();
}; ### is it a proper xml? broken xml may crash ZEBRA- slow but safe warn "ERROR: $error";
## it's Broken XML-- Should not reach here-- but if it does -lets protect ZEBRA # this doesn't exist, so no need to wail on zebra to delete it
if ($@){ if ($@->code() eq 13) {
Unix::Syslog::syslog LOG_ERR, "$@"; $ok = 1;
my $delsth=$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE id =?"); }
$delsth->execute($data->{'id'}); }
next; #if ($ok == 1) {
} # my $delsth=$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE id =?");
# ok, we have everything, do the operation in zebra ! # $delsth->execute($data->{'id'});
$ok=zebrado($marcxml,$data->{'operation'},$data->{'server'},$data->{'biblio_auth_number'}); # next;
} #}
if ($ok == 1){
$dbh=C4::Context->dbh; }
my $delsth; else {
# if it's a deletion, we can delete every request on this biblio : in case the user # it is an update
# did a modif (or item deletion) just before biblio deletion, there are some specialUpdate warn "Updating record" if $debug;
# that are pending and can't succeed, as we don't have the XML anymore # get the XML
# so, delete everything for this biblionumber my $marcxml;
if ($data->{'operation'} eq 'delete_record') { if ($data->{'server'} eq "biblioserver") {
$delsth =$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE biblio_auth_number =?"); my $marc = GetMarcBiblio($data->{'biblio_auth_number'});
$delsth->execute($data->{'biblio_auth_number'}); $marcxml = $marc->as_xml_record() if $marc;
# if it's not a deletion, delete every pending specialUpdate for this biblionumber }
# in case the user add biblio, then X items, before this script runs elsif ($data->{'server'} eq "authorityserver") {
# this avoid indexing X+1 times where just 1 is enough. $marcxml =C4::AuthoritiesMarc::GetAuthorityXML($data->{'biblio_auth_number'});
} else { }
$delsth =$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE biblio_auth_number =? and operation='specialUpdate'"); # check it's XML, just in case
$delsth->execute($data->{'biblio_auth_number'}); eval {
} my $hashed=XMLin($marcxml);
} }; ### is it a proper xml? broken xml may crash ZEBRA- slow but safe
}; ## it's Broken XML-- Should not reach here-- but if it does -lets protect ZEBRA
if ($@){ if ($@){
Unix::Syslog::syslog LOG_ERR, "$@"; Unix::Syslog::syslog LOG_ERR, "$@";
} my $delsth=$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE id =?");
} $delsth->execute($data->{'id'});
$readsth->finish(); next;
$kernel->yield('status_check'); }
# ok, we have everything, do the operation in zebra !
$ok=zebrado($marcxml,$data->{'operation'},$data->{'server'},$data->{'biblio_auth_number'});
}
if ($ok == 1){
$dbh=C4::Context->dbh;
my $delsth;
# if it's a deletion, we can delete every request on this biblio : in case the user
# did a modif (or item deletion) just before biblio deletion, there are some specialUpdate
# that are pending and can't succeed, as we don't have the XML anymore
# so, delete everything for this biblionumber
if ($data->{'operation'} eq 'delete_record') {
$delsth =$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE biblio_auth_number =?");
$delsth->execute($data->{'biblio_auth_number'});
# if it's not a deletion, delete every pending specialUpdate for this biblionumber
# in case the user add biblio, then X items, before this script runs
# this avoid indexing X+1 times where just 1 is enough.
} else {
$delsth =$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE biblio_auth_number =? and operation='specialUpdate'");
$delsth->execute($data->{'biblio_auth_number'});
}
}
};
if ($@){
Unix::Syslog::syslog LOG_ERR, "$@";
}
}
$readsth->finish();
$kernel->yield('status_check');
} }
sub zebrado { sub zebrado {
###Accepts a $server variable thus we can use it to update biblios, authorities or other zebra dbs ###Accepts a $server variable thus we can use it to update biblios, authorities or other zebra dbs
my ($record,$op,$server,$biblionumber)=@_; my ($record,$op,$server,$biblionumber)=@_;
warn "In zebrado" if $debug;
my @port; my @port;
my $tried=0; my $tried=0;
@ -150,29 +178,35 @@ sub zebrado {
my $reconnect=0; my $reconnect=0;
# $record=Encode::encode("UTF-8",$record); # $record=Encode::encode("UTF-8",$record);
my $shadow=$server."shadow"; my $shadow=$server."shadow";
$op = 'recordDelete' if $op eq 'delete_record'; $op = 'recordDelete' if $op eq 'delete_record';
reconnect: reconnect:
warn "At reconnect" if $debug;
my $Zconn=C4::Context->Zconn($server, 0, 1); my $Zconn=C4::Context->Zconn($server, 0, 1,'','xml');
if ($record){ if ($record){
warn "Record found" if $debug;
my $Zpackage = $Zconn->package(); my $Zpackage = $Zconn->package();
$Zpackage->option(action => $op); $Zpackage->option(action => $op);
$Zpackage->option(record => $record); $Zpackage->option(record => $record);
# $Zpackage->option(recordIdOpaque => $biblionumber) if $biblionumber; # $Zpackage->option(recordIdOpaque => $biblionumber) if $biblionumber;
retry: retry:
$Zpackage->send("update"); warn "At Retry" if $debug;
eval { $Zpackage->send("update") };
if ($@ && $@->isa("ZOOM::Exception")) {
print "Oops! ", $@->message(), "\n";
return $@->code();
}
my($error, $errmsg, $addinfo, $diagset) = $Zconn->error_x(); my($error, $errmsg, $addinfo, $diagset) = $Zconn->error_x();
if ($error==10007 && $tried<3) {## timeout --another 30 looonng seconds for this update if ($error==10007 && $tried<3) {## timeout --another 30 looonng seconds for this update
sleep 1; ## wait a sec! sleep 1; ## wait a sec!
$tried=$tried+1; $tried++;
goto "retry"; goto "retry";
}elsif ($error==2 && $tried<2) {## timeout --temporary zebra error !whatever that means }elsif ($error==2 && $tried<2) {## timeout --temporary zebra error !whatever that means
sleep 2; ## wait two seconds! sleep 2; ## wait two seconds!
$tried=$tried+1; $tried++;
goto "retry"; goto "retry";
}elsif($error==10004 && $recon==0){##Lost connection -reconnect }elsif($error==10004 && $recon==0){##Lost connection -reconnect
sleep 1; ## wait a sec! sleep 1; ## wait a sec!
$recon=1; $recon=1;
$Zpackage->destroy(); $Zpackage->destroy();
$Zconn->destroy(); $Zconn->destroy();
@ -183,7 +217,7 @@ retry:
return 0; return 0;
} }
$Zpackage->send('commit'); $Zpackage->send('commit');
return 1; return 1;
} }
return 0; return 0;
} }
@ -200,8 +234,8 @@ POE::Session->create(
inline_states => { inline_states => {
_start => \&handler_start, _start => \&handler_start,
sleep => \&handler_sleep, sleep => \&handler_sleep,
status_check => \&handler_check, status_check => \&handler_check,
do_ops => \&zebraop, do_ops => \&zebraop,
_stop => \&handler_stop, _stop => \&handler_stop,
}, },
); );