Ed Hoo has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/261317

Change subject: Use parser options to provide context to CargoStore persistence
......................................................................

Use parser options to provide context to CargoStore persistence

This improves thread safety preventing conflicts between saving individual 
pages and Recreate Data jobs.  Note however that duplicate rows mat still be 
created if (a) multiple saves for the same page are taking place and the delete 
of 2 or more of these updates take place before the inserts, or (b) the page is 
on queue to be recreated and it is saved before the recreation job gets to it.

Bug: T122564
Change-Id: Iee7cc92f1dc0fc6e90698adf74bd6a9baaeeff14
---
M Cargo.hooks.php
M CargoPopulateTableJob.php
M CargoUtils.php
M maintenance/cargoRecreateData.php
M parserfunctions/CargoStore.php
5 files changed, 72 insertions(+), 30 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Cargo 
refs/changes/17/261317/1

diff --git a/Cargo.hooks.php b/Cargo.hooks.php
index 9abbb8c..f0dd488 100644
--- a/Cargo.hooks.php
+++ b/Cargo.hooks.php
@@ -174,8 +174,7 @@
                // Even though the page will get parsed again after the save,
                // we need to parse it here anyway, for the settings we
                // added to remain set.
-               CargoStore::$settings['origin'] = 'page save';
-               CargoUtils::parsePageForStorage( $article->getTitle(), 
$content->getNativeData() );
+               CargoUtils::parsePageForStorage( $article->getTitle(), 
$content->getNativeData(), 'PageSave' );
 
                return true;
        }
@@ -190,7 +189,7 @@
                // this setting will be enough to get the correct revision of
                // this page to be saved by Cargo, since the page will be
                // parsed right after this.
-               CargoStore::$settings['origin'] = 'Approved Revs revision 
approved';
+               CargoStore::setParserContext($parser, 
'ApprovedRevsRevisionApproved');
                return true;
        }
 
@@ -201,7 +200,7 @@
                $pageID = $title->getArticleID();
                self::deletePageFromSystem( $pageID );
                // This is all we need - see onARRevisionApproved(), above.
-               CargoStore::$settings['origin'] = 'Approved Revs revision 
unapproved';
+               CargoStore::setParserContext($parser, 
'ApprovedRevsRevisionUnapproved');
                return true;
        }
 
diff --git a/CargoPopulateTableJob.php b/CargoPopulateTableJob.php
index 8f0499c..8abec90 100644
--- a/CargoPopulateTableJob.php
+++ b/CargoPopulateTableJob.php
@@ -42,17 +42,10 @@
                        $cdb->delete( $this->params['dbTableName'], array( 
'_pageID' => $article->getID() ) );
                }
 
-               // All we need to do here is set some global variables based
+               // All we need to do here is set some parser variables based
                // on the parameters of this job, then parse the page -
                // the #cargo_store function will take care of the rest.
-               CargoStore::$settings['origin'] = 'template';
-               CargoStore::$settings['dbTableName'] = 
$this->params['dbTableName'];
-               CargoUtils::parsePageForStorage( $this->title, 
$article->getContent() );
-
-               // We need to unset this, if the job was called via runJobs.php,
-               // so that it doesn't affect other (non-Cargo) jobs, like page
-               // refreshes.
-               unset( CargoStore::$settings['origin'] );
+               CargoUtils::parsePageForStorage( $this->title, 
$article->getContent(), 'Template', $this->params['dbTableName'] );
 
                wfProfileOut( __METHOD__ );
                return true;
diff --git a/CargoUtils.php b/CargoUtils.php
index e1ad9fd..9c33263 100644
--- a/CargoUtils.php
+++ b/CargoUtils.php
@@ -360,7 +360,7 @@
                return $value;
        }
 
-       public static function parsePageForStorage( $title, $pageContents ) {
+       public static function parsePageForStorage( $title, $pageContents, 
$savingContext, $populatedTable = false ) {
                // @TODO - is there a "cleaner" way to get a page to be parsed?
                global $wgParser;
 
@@ -375,7 +375,10 @@
                } else {
                        $pageText = $pageContents;
                }
-               $wgParser->parse( $pageText, $title, new ParserOptions() );
+
+               $parserOptions = new ParserOptions();
+               CargoStore::setParserOptionsContext( $parserOptions, 
$savingContext, $populatedTable );
+               $wgParser->parse( $pageText, $title, $parserOptions );
        }
 
        /**
diff --git a/maintenance/cargoRecreateData.php 
b/maintenance/cargoRecreateData.php
index c7e19ae..b0fc9c6 100644
--- a/maintenance/cargoRecreateData.php
+++ b/maintenance/cargoRecreateData.php
@@ -114,15 +114,13 @@
                                }
 
                                foreach( $titlesWithThisTemplate as $title ) {
-                                       // All we need to do here is set some 
global variables based
+                                       // All we need to do here is set some 
parser variables based
                                        // on the parameters of this job, then 
parse the page -
                                        // the #cargo_store function will take 
care of the rest.
-                                       CargoStore::$settings['origin'] = 
'template';
-                                       CargoStore::$settings['dbTableName'] = 
$tableName;
                                        $wikiPage = WikiPage::newFromID( 
$title->getArticleID() );
                                        $content = $wikiPage->getContent();
                                        $contentText = 
ContentHandler::getContentText( $content );
-                                       CargoUtils::parsePageForStorage( 
$title, $contentText );
+                                       CargoUtils::parsePageForStorage( 
$title, $contentText, 'Template', $tableName );
                                }
                                $offset += 500;
                        } while ( count( $titlesWithThisTemplate ) == 500 );
diff --git a/parserfunctions/CargoStore.php b/parserfunctions/CargoStore.php
index 2c4c49e..41e0129 100644
--- a/parserfunctions/CargoStore.php
+++ b/parserfunctions/CargoStore.php
@@ -8,7 +8,7 @@
 
 class CargoStore {
 
-       public static $settings = array();
+       private static $settings = array();
 
        const DATE_AND_TIME = 0;
        const DATE_ONLY = 1;
@@ -28,11 +28,11 @@
                // This function does actual DB modifications - so only proceed
                // is this is called via either a page save or a "recreate
                // data" action for a template that this page calls.
-               if ( count( self::$settings ) == 0 ) {
+
+               $populatedTable = false;
+               $savingContext = self::getContext( $parser->getOptions(), 
$populatedTable );
+               if ( ! $savingContext ) {
                        wfDebugLog( 'cargo', "CargoStore::run() - skipping.\n" 
);
-                       return;
-               } elseif ( !array_key_exists( 'origin', self::$settings ) ) {
-                       wfDebugLog( 'cargo', "CargoStore::run() - skipping 
2.\n" );
                        return;
                }
 
@@ -79,14 +79,10 @@
                        }
                }
 
-               if ( $tableName == '' ) {
-                       return;
-               }
-
-               if ( self::$settings['origin'] == 'template' ) {
+               if ( $savingContext == 'Template' ) {
                        // It came from a template "recreate data" action -
                        // make sure it passes various criteria.
-                       if ( self::$settings['dbTableName'] != $tableName ) {
+                       if ( $populatedTable != $tableName ) {
                                wfDebugLog( 'cargo', "CargoStore::run() - 
skipping 4.\n" );
                                return;
                        }
@@ -331,4 +327,57 @@
                }
        }
 
+       /**
+        * Set the context for the CargoStore::run callback
+        * The context is set by adding extra keys to the parser options
+     */
+       public static function setParserContext(&$parser, $savingContext, 
$populatedTable = false ) {
+               if ( $savingContext ) {
+                       
$parser->getOptions()->addExtraKey('CargoOrigin_'.$savingContext);
+               }
+               if ( $populatedTable ) {
+                       
$parser->getOptions()->addExtraKey('CargoTable_'.$populatedTable);
+               }
+       }
+
+       /**
+        * Set the context for the CargoStore::run callback
+        * The context is set by adding extra keys to the parser options
+     */
+       public static function setParserOptionsContext(&$parserOptions, 
$savingContext, $populatedTable = false ) {
+               if ( $savingContext ) {
+                       
$parserOptions->addExtraKey('CargoOrigin_'.$savingContext);
+               }
+               if ( $populatedTable ) {
+                       
$parserOptions->addExtraKey('CargoTable_'.$populatedTable);
+               }
+       }
+
+       /**
+        * Retrieves the context for the CargoStore::run callback
+        * The context is set by adding extra keys to the parser options
+     */
+       public static function getContext($parserOptions, &$populatedTable ) {
+               $options = explode( '!', $parserOptions->optionsHash( Array() ) 
);
+               $savingContext = false;
+               $populatedTable = false;
+
+               for ( $i =0 ; $i < count($options) ; $i++) {
+                       $thisOption = $options[$i];
+                       if ( substr( $thisOption, 0, 5 ) == 'Cargo' ) {
+                               $key = explode( '_', $thisOption )[0];
+                               $value = substr( $thisOption, strlen($key) + 1 
);
+                               switch ( $key ) {
+                                       case 'CargoOrigin':
+                                               $savingContext = $value;
+                                               break;
+                                       case 'CargoTable':
+                                               $populatedTable = $value;
+                                               break;
+                               }
+                       }
+               }
+               return $savingContext;
+       }
+
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/261317
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iee7cc92f1dc0fc6e90698adf74bd6a9baaeeff14
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Cargo
Gerrit-Branch: master
Gerrit-Owner: Ed Hoo <edward....@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to