diff options
author | Catrope <roan.kattouw@gmail.com> | 2013-01-15 15:32:10 -0800 |
---|---|---|
committer | Gerrit Code Review <gerrit@wikimedia.org> | 2013-01-16 03:10:26 +0000 |
commit | e2e8461fd23d81aa3c89a56245053c6d3f06da84 (patch) | |
tree | f2fb568eee213fc01820e54c43ac2e4c9e9ce35a /includes/MessageBlobStore.php | |
parent | ab8de17e0f7bc40eecee7d9e32cd0ccd9e783610 (diff) | |
download | mediawikicore-e2e8461fd23d81aa3c89a56245053c6d3f06da84.tar.gz mediawikicore-e2e8461fd23d81aa3c89a56245053c6d3f06da84.zip |
(bug 31044) Make ResourceLoader behave in read-only mode
When the database is in read-only mode or writes fail for some other
reason, ResourceLoader should make every attempt to still serve JS and
CSS correctly.
* Surround a bunch of DB write code in MessageBlobStore.php in try-catch
blocks.
* Surround the DB write in ResourceLoaderFileModule.php in a try-catch
block rather than checking wfReadOnly(), because the DB may fail for
other reasons.
* In ResourceLoader::respond() and helpers, set a short cache timeout on
responses that include commented-out error messages.
Change-Id: Idc83a0fe042806263f9337c40ade8c38c56aa3cd
Diffstat (limited to 'includes/MessageBlobStore.php')
-rw-r--r-- | includes/MessageBlobStore.php | 218 |
1 files changed, 116 insertions, 102 deletions
diff --git a/includes/MessageBlobStore.php b/includes/MessageBlobStore.php index 09561bd78ae7..6322be7565b3 100644 --- a/includes/MessageBlobStore.php +++ b/includes/MessageBlobStore.php @@ -80,42 +80,45 @@ class MessageBlobStore { return false; } - $dbw = wfGetDB( DB_MASTER ); - $success = $dbw->insert( 'msg_resource', array( - 'mr_lang' => $lang, - 'mr_resource' => $name, - 'mr_blob' => $blob, - 'mr_timestamp' => $dbw->timestamp() - ), - __METHOD__, - array( 'IGNORE' ) - ); - - if ( $success ) { - if ( $dbw->affectedRows() == 0 ) { - // Blob was already present, fetch it - $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array( - 'mr_resource' => $name, - 'mr_lang' => $lang, - ), - __METHOD__ - ); - } else { - // Update msg_resource_links - $rows = array(); + try { + $dbw = wfGetDB( DB_MASTER ); + $success = $dbw->insert( 'msg_resource', array( + 'mr_lang' => $lang, + 'mr_resource' => $name, + 'mr_blob' => $blob, + 'mr_timestamp' => $dbw->timestamp() + ), + __METHOD__, + array( 'IGNORE' ) + ); - foreach ( $module->getMessages() as $key ) { - $rows[] = array( - 'mrl_resource' => $name, - 'mrl_message' => $key + if ( $success ) { + if ( $dbw->affectedRows() == 0 ) { + // Blob was already present, fetch it + $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array( + 'mr_resource' => $name, + 'mr_lang' => $lang, + ), + __METHOD__ + ); + } else { + // Update msg_resource_links + $rows = array(); + + foreach ( $module->getMessages() as $key ) { + $rows[] = array( + 'mrl_resource' => $name, + 'mrl_message' => $key + ); + } + $dbw->insert( 'msg_resource_links', $rows, + __METHOD__, array( 'IGNORE' ) ); } - $dbw->insert( 'msg_resource_links', $rows, - __METHOD__, array( 'IGNORE' ) - ); } + } catch ( Exception $e ) { + wfDebug( __METHOD__ . " failed to update DB: $e\n" ); } - return $blob; } @@ -141,48 +144,51 @@ class MessageBlobStore { $oldBlob = $row->mr_blob; $newBlob = self::generateMessageBlob( $module, $lang ); - $newRow = array( - 'mr_resource' => $name, - 'mr_lang' => $lang, - 'mr_blob' => $newBlob, - 'mr_timestamp' => $dbw->timestamp() - ); + try { + $newRow = array( + 'mr_resource' => $name, + 'mr_lang' => $lang, + 'mr_blob' => $newBlob, + 'mr_timestamp' => $dbw->timestamp() + ); - $dbw->replace( 'msg_resource', - array( array( 'mr_resource', 'mr_lang' ) ), - $newRow, __METHOD__ - ); + $dbw->replace( 'msg_resource', + array( array( 'mr_resource', 'mr_lang' ) ), + $newRow, __METHOD__ + ); - // Figure out which messages were added and removed - $oldMessages = array_keys( FormatJson::decode( $oldBlob, true ) ); - $newMessages = array_keys( FormatJson::decode( $newBlob, true ) ); - $added = array_diff( $newMessages, $oldMessages ); - $removed = array_diff( $oldMessages, $newMessages ); + // Figure out which messages were added and removed + $oldMessages = array_keys( FormatJson::decode( $oldBlob, true ) ); + $newMessages = array_keys( FormatJson::decode( $newBlob, true ) ); + $added = array_diff( $newMessages, $oldMessages ); + $removed = array_diff( $oldMessages, $newMessages ); - // Delete removed messages, insert added ones - if ( $removed ) { - $dbw->delete( 'msg_resource_links', array( - 'mrl_resource' => $name, - 'mrl_message' => $removed - ), __METHOD__ - ); - } + // Delete removed messages, insert added ones + if ( $removed ) { + $dbw->delete( 'msg_resource_links', array( + 'mrl_resource' => $name, + 'mrl_message' => $removed + ), __METHOD__ + ); + } - $newLinksRows = array(); + $newLinksRows = array(); - foreach ( $added as $message ) { - $newLinksRows[] = array( - 'mrl_resource' => $name, - 'mrl_message' => $message - ); - } + foreach ( $added as $message ) { + $newLinksRows[] = array( + 'mrl_resource' => $name, + 'mrl_message' => $message + ); + } - if ( $newLinksRows ) { - $dbw->insert( 'msg_resource_links', $newLinksRows, __METHOD__, - array( 'IGNORE' ) // just in case - ); + if ( $newLinksRows ) { + $dbw->insert( 'msg_resource_links', $newLinksRows, __METHOD__, + array( 'IGNORE' ) // just in case + ); + } + } catch ( Exception $e ) { + wfDebug( __METHOD__ . " failed to update DB: $e\n" ); } - return $newBlob; } @@ -192,50 +198,58 @@ class MessageBlobStore { * @param $key String: message key */ public static function updateMessage( $key ) { - $dbw = wfGetDB( DB_MASTER ); - - // Keep running until the updates queue is empty. - // Due to update conflicts, the queue might not be emptied - // in one iteration. - $updates = null; - do { - $updates = self::getUpdatesForMessage( $key, $updates ); - - foreach ( $updates as $k => $update ) { - // Update the row on the condition that it - // didn't change since we fetched it by putting - // the timestamp in the WHERE clause. - $success = $dbw->update( 'msg_resource', - array( - 'mr_blob' => $update['newBlob'], - 'mr_timestamp' => $dbw->timestamp() ), - array( - 'mr_resource' => $update['resource'], - 'mr_lang' => $update['lang'], - 'mr_timestamp' => $update['timestamp'] ), - __METHOD__ - ); + try { + $dbw = wfGetDB( DB_MASTER ); + + // Keep running until the updates queue is empty. + // Due to update conflicts, the queue might not be emptied + // in one iteration. + $updates = null; + do { + $updates = self::getUpdatesForMessage( $key, $updates ); + + foreach ( $updates as $k => $update ) { + // Update the row on the condition that it + // didn't change since we fetched it by putting + // the timestamp in the WHERE clause. + $success = $dbw->update( 'msg_resource', + array( + 'mr_blob' => $update['newBlob'], + 'mr_timestamp' => $dbw->timestamp() ), + array( + 'mr_resource' => $update['resource'], + 'mr_lang' => $update['lang'], + 'mr_timestamp' => $update['timestamp'] ), + __METHOD__ + ); - // Only requeue conflicted updates. - // If update() returned false, don't retry, for - // fear of getting into an infinite loop - if ( !( $success && $dbw->affectedRows() == 0 ) ) { - // Not conflicted - unset( $updates[$k] ); + // Only requeue conflicted updates. + // If update() returned false, don't retry, for + // fear of getting into an infinite loop + if ( !( $success && $dbw->affectedRows() == 0 ) ) { + // Not conflicted + unset( $updates[$k] ); + } } - } - } while ( count( $updates ) ); + } while ( count( $updates ) ); - // No need to update msg_resource_links because we didn't add - // or remove any messages, we just changed their contents. + // No need to update msg_resource_links because we didn't add + // or remove any messages, we just changed their contents. + } catch ( Exception $e ) { + wfDebug( __METHOD__ . " failed to update DB: $e\n" ); + } } public static function clear() { // TODO: Give this some more thought // TODO: Is TRUNCATE better? - $dbw = wfGetDB( DB_MASTER ); - $dbw->delete( 'msg_resource', '*', __METHOD__ ); - $dbw->delete( 'msg_resource_links', '*', __METHOD__ ); + try { + $dbw = wfGetDB( DB_MASTER ); + $dbw->delete( 'msg_resource', '*', __METHOD__ ); + $dbw->delete( 'msg_resource_links', '*', __METHOD__ ); + } catch ( Exception $e ) { + wfDebug( __METHOD__ . " failed to update DB: $e\n" ); + } } /** |