Refactor database initialisation in feedlog.pl.
* Move database initialisation to a separate function. * (Re-)try to connect every five seconds (instead of going into an endless loop) and log successful (re-)connections. * Log postings that are dropped due to database failures to syslog (Message-ID) for recovery. * If the connection to the database is lost, try to recover it (every five seconds) and try again to write the pending data. * Input will be buffered automatically by INN until feedlog is able to process it (see man 5 newsfeeds). Fixes #30, #31. Signed-off-by: Thomas Hochstein <thh@inter.net>
This commit is contained in:
parent
c3973e7d0d
commit
98563c619e
3
doc/TODO
3
doc/TODO
|
@ -46,9 +46,6 @@ Bug numbers refer to the Mantis issue tracker at <http://bugs.th-h.de/>.
|
||||||
- General tests and optimisations
|
- General tests and optimisations
|
||||||
|
|
||||||
+ feedlog.pl
|
+ feedlog.pl
|
||||||
- Gracefully handle interruptions to database connection, at least log
|
|
||||||
lost postings (Bug #30).
|
|
||||||
- Buffer output that cannot be written to database (Bug #31).
|
|
||||||
- Add / enhance / test error handling
|
- Add / enhance / test error handling
|
||||||
- General tests and optimisations
|
- General tests and optimisations
|
||||||
|
|
||||||
|
|
63
feedlog.pl
63
feedlog.pl
|
@ -28,6 +28,42 @@ use DBI;
|
||||||
use Getopt::Long qw(GetOptions);
|
use Getopt::Long qw(GetOptions);
|
||||||
Getopt::Long::config ('bundling');
|
Getopt::Long::config ('bundling');
|
||||||
|
|
||||||
|
################################# Subroutines ##################################
|
||||||
|
|
||||||
|
sub PrepareDB {
|
||||||
|
### initialise database connection, prepare statement
|
||||||
|
### and catch errors
|
||||||
|
### IN : \%Conf : reference to configuration hash
|
||||||
|
### OUT: $DBHandle: database handle
|
||||||
|
### $DBQuery : prepared statement
|
||||||
|
our ($DBHandle, $DBQuery, $OptQuiet);
|
||||||
|
my ($ConfigR) = @_;
|
||||||
|
my %Conf = %$ConfigR;
|
||||||
|
# drop current database connection - hard, if necessary
|
||||||
|
if ($DBHandle) {
|
||||||
|
$DBHandle->disconnect;
|
||||||
|
undef $DBHandle;
|
||||||
|
};
|
||||||
|
# connect to database; try again every 5 seconds
|
||||||
|
while (!$DBHandle) {
|
||||||
|
$DBHandle = InitDB($ConfigR,0);
|
||||||
|
if (!$DBHandle) {
|
||||||
|
syslog(LOG_CRIT, 'Database connection failed: %s', $DBI::errstr);
|
||||||
|
sleep(5);
|
||||||
|
} else {;
|
||||||
|
syslog(LOG_NOTICE, "Database connection (re-)established successfully.") if !$OptQuiet;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$DBQuery = $DBHandle->prepare(sprintf("INSERT INTO %s.%s (day,date,mid,
|
||||||
|
timestamp,token,size,peer,path,
|
||||||
|
newsgroups,headers)
|
||||||
|
VALUES (?,?,?,?,?,?,?,?,?,?)",
|
||||||
|
$Conf{'DBDatabase'},
|
||||||
|
$Conf{'DBTableRaw'}));
|
||||||
|
return ($DBHandle,$DBQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
################################# Main program #################################
|
################################# Main program #################################
|
||||||
|
|
||||||
### read commandline options
|
### read commandline options
|
||||||
|
@ -45,16 +81,7 @@ openlog($0, 'nofatal,pid', LOG_NEWS);
|
||||||
syslog(LOG_NOTICE, "$MyVersion starting up.") if !$OptQuiet;
|
syslog(LOG_NOTICE, "$MyVersion starting up.") if !$OptQuiet;
|
||||||
|
|
||||||
### init database
|
### init database
|
||||||
my $DBHandle = InitDB(\%Conf,0);
|
my ($DBHandle,$DBQuery) = PrepareDB(\%Conf);
|
||||||
if (!$DBHandle) {
|
|
||||||
syslog(LOG_CRIT, 'Database connection failed: %s', $DBI::errstr);
|
|
||||||
while (1) {}; # go into endless loop to suppress further errors and respawning
|
|
||||||
};
|
|
||||||
my $DBQuery = $DBHandle->prepare(sprintf("INSERT INTO %s.%s (day,date,mid,
|
|
||||||
timestamp,token,size,peer,path,
|
|
||||||
newsgroups,headers)
|
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?)",
|
|
||||||
$Conf{'DBDatabase'},$Conf{'DBTableRaw'}));
|
|
||||||
|
|
||||||
### main loop
|
### main loop
|
||||||
while (<>) {
|
while (<>) {
|
||||||
|
@ -84,7 +111,21 @@ while (<>) {
|
||||||
# write to database
|
# write to database
|
||||||
if (!$DBQuery->execute($Day, $Date, $Mid, $Timestamp, $Token, $Size, $Peer,
|
if (!$DBQuery->execute($Day, $Date, $Mid, $Timestamp, $Token, $Size, $Peer,
|
||||||
$Path, $Newsgroups, $Headers)) {
|
$Path, $Newsgroups, $Headers)) {
|
||||||
syslog(LOG_ERR, 'Database error: %s', $DBI::errstr);
|
syslog(LOG_ERR, 'Database error %s while processing %s: %s',
|
||||||
|
$DBI::err, $Mid, $DBI::errstr);
|
||||||
|
# if "MySQL server has gone away", try to recover
|
||||||
|
if ($DBI::err == 2006) {
|
||||||
|
# try to reconnect to database
|
||||||
|
($DBHandle,$DBQuery) = PrepareDB(\%Conf);
|
||||||
|
# try to repeat the write attempt as before
|
||||||
|
if (!$DBQuery->execute($Day, $Date, $Mid, $Timestamp, $Token, $Size, $Peer,
|
||||||
|
$Path, $Newsgroups, $Headers)) {
|
||||||
|
syslog(LOG_ERR, '%s was dropped and lost.',$Mid);
|
||||||
|
};
|
||||||
|
# otherwise log missing posting
|
||||||
|
} else {
|
||||||
|
syslog(LOG_ERR, '%s was dropped and lost.',$Mid);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
$DBQuery->finish;
|
$DBQuery->finish;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue