Merge pull request #9566 from annando/update-foo

Avoid multiple database update mails, changed log level
This commit is contained in:
Hypolite Petovan 2020-11-21 10:53:06 -05:00 committed by GitHub
commit e6362c4923
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 60 deletions

View file

@ -41,7 +41,7 @@ class Update
* *
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function check($basePath, $via_worker, App\Mode $mode) public static function check(string $basePath, bool $via_worker, App\Mode $mode)
{ {
if (!DBA::connected()) { if (!DBA::connected()) {
return; return;
@ -80,15 +80,15 @@ class Update
* Automatic database updates * Automatic database updates
* *
* @param string $basePath The base path of this application * @param string $basePath The base path of this application
* @param bool $force Force the Update-Check even if the database version doesn't match * @param bool $force Force the Update-Check even if the database version doesn't match
* @param bool $override Overrides any running/stuck updates * @param bool $override Overrides any running/stuck updates
* @param bool $verbose Run the Update-Check verbose * @param bool $verbose Run the Update-Check verbose
* @param bool $sendMail Sends a Mail to the administrator in case of success/failure * @param bool $sendMail Sends a Mail to the administrator in case of success/failure
* *
* @return string Empty string if the update is successful, error messages otherwise * @return string Empty string if the update is successful, error messages otherwise
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function run($basePath, $force = false, $override = false, $verbose = false, $sendMail = true) public static function run(string $basePath, bool $force = false, bool $override = false, bool $verbose = false, bool $sendMail = true)
{ {
// In force mode, we release the dbupdate lock first // In force mode, we release the dbupdate lock first
// Necessary in case of an stuck update // Necessary in case of an stuck update
@ -111,11 +111,11 @@ class Update
if ($stored < $current || $force) { if ($stored < $current || $force) {
DI::config()->load('database'); DI::config()->load('database');
Logger::notice('Update starting.', ['from' => $stored, 'to' => $current]);
// Compare the current structure with the defined structure // Compare the current structure with the defined structure
// If the Lock is acquired, never release it automatically to avoid double updates // If the Lock is acquired, never release it automatically to avoid double updates
if (DI::lock()->acquire('dbupdate', 120, Cache\Duration::INFINITE)) { if (DI::lock()->acquire('dbupdate', 0, Cache\Duration::INFINITE)) {
Logger::notice('Update starting.', ['from' => $stored, 'to' => $current]);
// Checks if the build changed during Lock acquiring (so no double update occurs) // Checks if the build changed during Lock acquiring (so no double update occurs)
$retryBuild = DI::config()->get('system', 'build', null, true); $retryBuild = DI::config()->get('system', 'build', null, true);
@ -126,17 +126,21 @@ class Update
} }
// run the pre_update_nnnn functions in update.php // run the pre_update_nnnn functions in update.php
for ($x = $stored + 1; $x <= $current; $x++) { for ($version = $stored + 1; $version <= $current; $version++) {
$r = self::runUpdateFunction($x, 'pre_update', $sendMail); Logger::notice('Execute pre update.', ['version' => $version]);
$r = self::runUpdateFunction($version, 'pre_update', $sendMail);
if (!$r) { if (!$r) {
Logger::warning('Pre update failed', ['version' => $x]); Logger::warning('Pre update failed', ['version' => $version]);
DI::config()->set('system', 'update', Update::FAILED); DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate'); DI::lock()->release('dbupdate');
return $r; return $r;
} else {
Logger::notice('Pre update executed.', ['version' => $version]);
} }
} }
// update the structure in one call // update the structure in one call
Logger::notice('Execute structure update');
$retval = DBStructure::update($basePath, $verbose, true); $retval = DBStructure::update($basePath, $verbose, true);
if (!empty($retval)) { if (!empty($retval)) {
if ($sendMail) { if ($sendMail) {
@ -150,29 +154,32 @@ class Update
DI::lock()->release('dbupdate'); DI::lock()->release('dbupdate');
return $retval; return $retval;
} else { } else {
DI::config()->set('database', 'last_successful_update', $current); Logger::notice('Database structure update finished.', ['from' => $stored, 'to' => $current]);
DI::config()->set('database', 'last_successful_update_time', time());
Logger::info('Update finished.', ['from' => $stored, 'to' => $current]);
} }
// run the update_nnnn functions in update.php // run the update_nnnn functions in update.php
for ($x = $stored + 1; $x <= $current; $x++) { for ($version = $stored + 1; $version <= $current; $version++) {
$r = self::runUpdateFunction($x, 'update', $sendMail); Logger::notice('Execute post update.', ['version' => $version]);
$r = self::runUpdateFunction($version, 'update', $sendMail);
if (!$r) { if (!$r) {
Logger::warning('Post update failed', ['version' => $x]); Logger::warning('Post update failed', ['version' => $version]);
DI::config()->set('system', 'update', Update::FAILED); DI::config()->set('system', 'update', Update::FAILED);
DI::lock()->release('dbupdate'); DI::lock()->release('dbupdate');
return $r; return $r;
} else {
DI::config()->set('system', 'build', $version);
Logger::notice('Post update executed.', ['version' => $version]);
} }
} }
Logger::notice('Update success.', ['from' => $stored, 'to' => $current]); DI::config()->set('system', 'build', $current);
if ($sendMail) {
self::updateSuccessfull($stored, $current);
}
DI::config()->set('system', 'update', Update::SUCCESS); DI::config()->set('system', 'update', Update::SUCCESS);
DI::lock()->release('dbupdate'); DI::lock()->release('dbupdate');
Logger::notice('Update success.', ['from' => $stored, 'to' => $current]);
if ($sendMail) {
self::updateSuccessful($stored, $current);
}
} }
} }
} }
@ -183,18 +190,18 @@ class Update
/** /**
* Executes a specific update function * Executes a specific update function
* *
* @param int $x the DB version number of the function * @param int $version the DB version number of the function
* @param string $prefix the prefix of the function (update, pre_update) * @param string $prefix the prefix of the function (update, pre_update)
* @param bool $sendMail whether to send emails on success/failure * @param bool $sendMail whether to send emails on success/failure
* @return bool true, if the update function worked * @return bool true, if the update function worked
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function runUpdateFunction($x, $prefix, bool $sendMail = true) public static function runUpdateFunction(int $version, string $prefix, bool $sendMail = true)
{ {
$funcname = $prefix . '_' . $x; $funcname = $prefix . '_' . $version;
Logger::info('Update function start.', ['function' => $funcname]); Logger::notice('Update function start.', ['function' => $funcname]);
if (function_exists($funcname)) { if (function_exists($funcname)) {
// There could be a lot of processes running or about to run. // There could be a lot of processes running or about to run.
@ -207,46 +214,32 @@ class Update
if (DI::lock()->acquire('dbupdate_function', 120, Cache\Duration::INFINITE)) { if (DI::lock()->acquire('dbupdate_function', 120, Cache\Duration::INFINITE)) {
// call the specific update // call the specific update
Logger::info('Pre update function start.', ['function' => $funcname]); Logger::notice('Pre update function start.', ['function' => $funcname]);
$retval = $funcname(); $retval = $funcname();
Logger::info('Update function done.', ['function' => $funcname]); Logger::notice('Update function done.', ['function' => $funcname]);
if ($retval) { if ($retval) {
if ($sendMail) { if ($sendMail) {
//send the administrator an e-mail //send the administrator an e-mail
self::updateFailed( self::updateFailed(
$x, $version,
DI::l10n()->t('Update %s failed. See error logs.', $x) DI::l10n()->t('Update %s failed. See error logs.', $version)
); );
} }
Logger::error('Update function ERROR.', ['function' => $funcname, 'retval' => $retval]); Logger::error('Update function ERROR.', ['function' => $funcname, 'retval' => $retval]);
DI::lock()->release('dbupdate_function'); DI::lock()->release('dbupdate_function');
return false; return false;
} else { } else {
DI::config()->set('database', 'last_successful_update_function', $funcname);
DI::config()->set('database', 'last_successful_update_function_time', time());
if ($prefix == 'update') {
DI::config()->set('system', 'build', $x);
}
DI::lock()->release('dbupdate_function'); DI::lock()->release('dbupdate_function');
Logger::info('Update function finished.', ['function' => $funcname]); Logger::notice('Update function finished.', ['function' => $funcname]);
return true; return true;
} }
} else { } else {
Logger::error('Locking failed.', ['function' => $funcname]); Logger::error('Locking failed.', ['function' => $funcname]);
return false;
} }
} else { } else {
Logger::info('Update function skipped.', ['function' => $funcname]); Logger::notice('Update function skipped.', ['function' => $funcname]);
DI::config()->set('database', 'last_successful_update_function', $funcname);
DI::config()->set('database', 'last_successful_update_function_time', time());
if ($prefix == 'update') {
DI::config()->set('system', 'build', $x);
}
return true; return true;
} }
} }
@ -258,9 +251,9 @@ class Update
* @param string $error_message error message * @param string $error_message error message
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
private static function updateFailed($update_id, $error_message) { private static function updateFailed(int $update_id, string $error_message) {
//send the administrators an e-mail //send the administrators an e-mail
$condition = ['email' => explode(",", str_replace(" ", "", DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0]; $condition = ['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0];
$adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]); $adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]);
// No valid result? // No valid result?
@ -289,7 +282,7 @@ class Update
This needs to be fixed soon and I can't do it alone. Please contact a This needs to be fixed soon and I can't do it alone. Please contact a
friendica developer if you can not help me on your own. My database might be invalid.", friendica developer if you can not help me on your own. My database might be invalid.",
$update_id)); $update_id));
$body = $l10n->t("The error message is\n[pre]%s[/pre]", $error_message); $body = $l10n->t('The error message is\n[pre]%s[/pre]', $error_message);
$email = DI::emailer() $email = DI::emailer()
->newSystemMail() ->newSystemMail()
@ -300,14 +293,20 @@ class Update
DI::emailer()->send($email); DI::emailer()->send($email);
} }
//try the logger Logger::alert('Database structure update failed.', ['error' => $error_message]);
Logger::alert('Database structure update FAILED.', ['error' => $error_message]);
} }
private static function updateSuccessfull($from_build, $to_build) /**
* Send a mail to the administrator about the successful update
*
* @param integer $from_build
* @param integer $to_build
* @return void
*/
private static function updateSuccessful(int $from_build, int $to_build)
{ {
//send the administrators an e-mail //send the administrators an e-mail
$condition = ['email' => explode(",", str_replace(" ", "", DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0]; $condition = ['email' => explode(',', str_replace(' ', '', DI::config()->get('config', 'admin_email'))), 'parent-uid' => 0];
$adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]); $adminlist = DBA::select('user', ['uid', 'language', 'email'], $condition, ['order' => ['uid']]);
if (DBA::isResult($adminlist)) { if (DBA::isResult($adminlist)) {
@ -323,8 +322,8 @@ class Update
$lang = (($admin['language']) ? $admin['language'] : 'en'); $lang = (($admin['language']) ? $admin['language'] : 'en');
$l10n = DI::l10n()->withLang($lang); $l10n = DI::l10n()->withLang($lang);
$preamble = Strings::deindent($l10n->t(" $preamble = Strings::deindent($l10n->t('
The friendica database was successfully updated from %s to %s.", The friendica database was successfully updated from %s to %s.',
$from_build, $to_build)); $from_build, $to_build));
$email = DI::emailer() $email = DI::emailer()
@ -337,7 +336,6 @@ class Update
} }
} }
//try the logger
Logger::debug('Database structure update successful.'); Logger::debug('Database structure update successful.');
} }
} }

View file

@ -57,8 +57,6 @@ class DBSync extends BaseAdmin
$retval = DBStructure::update($a->getBasePath(), false, true); $retval = DBStructure::update($a->getBasePath(), false, true);
if ($retval === '') { if ($retval === '') {
$o = DI::l10n()->t("Database structure update %s was successfully applied.", DB_UPDATE_VERSION) . "<br />"; $o = DI::l10n()->t("Database structure update %s was successfully applied.", DB_UPDATE_VERSION) . "<br />";
DI::config()->set('database', 'last_successful_update', DB_UPDATE_VERSION);
DI::config()->set('database', 'last_successful_update_time', time());
} else { } else {
$o = DI::l10n()->t("Executing of database structure update %s failed with error: %s", DB_UPDATE_VERSION, $retval) . "<br />"; $o = DI::l10n()->t("Executing of database structure update %s failed with error: %s", DB_UPDATE_VERSION, $retval) . "<br />";
} }