Aaron Schulz has uploaded a new change for review.
https://gerrit.wikimedia.org/r/184463
Change subject: Introduced LazyDataUpdate class
......................................................................
Introduced LazyDataUpdate class
* ParserOutput now accepts these objects as updates, and resolves them on
the fly in the accessor.
* Made the edit stash API cache the parser output only if all the updates
are serializable or implicit.
Bug: T86305
Change-Id: I9499aaf2e8501a0db8a24e244cacd9a65518a7b2
---
M autoload.php
M includes/api/ApiStashEdit.php
M includes/parser/ParserOutput.php
3 files changed, 53 insertions(+), 20 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/63/184463/1
diff --git a/autoload.php b/autoload.php
index 674d4b0..da48c0f 100644
--- a/autoload.php
+++ b/autoload.php
@@ -637,6 +637,7 @@
'LanguageZh_hans' => __DIR__ . '/languages/classes/LanguageZh_hans.php',
'Languages' => __DIR__ . '/maintenance/language/languages.inc',
'LayeredParameterizedPassword' => __DIR__ .
'/includes/password/LayeredParameterizedPassword.php',
+ 'LazyDataUpdate' => __DIR__ . '/includes/deferred/LazyDataUpdate.php',
'LegacyLogFormatter' => __DIR__ . '/includes/logging/LogFormatter.php',
'License' => __DIR__ . '/includes/Licenses.php',
'Licenses' => __DIR__ . '/includes/Licenses.php',
diff --git a/includes/api/ApiStashEdit.php b/includes/api/ApiStashEdit.php
index 09489e4..44e5490 100644
--- a/includes/api/ApiStashEdit.php
+++ b/includes/api/ApiStashEdit.php
@@ -336,9 +336,9 @@
// Note: ParserOutput with that contains secondary data update
callbacks can not be
// stashed, since the callbacks are not serializable (see
ParserOutput::__sleep).
- $hasCustomDataUpdates = $parserOutput->hasCustomDataUpdates();
+ $fullySerializable =
$parserOutput->areSecondaryUpdatesSerializable();
- if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) &&
!$hasCustomDataUpdates ) {
+ if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) &&
$fullySerializable ) {
// Only store what is actually needed
$stashInfo = (object)array(
'pstContent' => $pstContent,
diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php
index 117e04a..7d3e804 100644
--- a/includes/parser/ParserOutput.php
+++ b/includes/parser/ParserOutput.php
@@ -53,7 +53,7 @@
$mTOCEnabled = true; # Whether TOC should be shown,
can't override __NOTOC__
private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other
value will result in no change.
private $mAccessedOptions = array(); # List of ParserOptions (stored in
the keys)
- private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to
save info from the page somewhere else.
+ private $mSecondaryDataUpdates = array(); # List of data updates
objects, used to save info from the page somewhere else.
private $mCustomDataUpdateCount = 0; # Number of custom updaters in
$mSecondaryDataUpdates.
private $mExtensionData = array(); # extra data used by extensions
private $mLimitReportData = array(); # Parser limit report data
@@ -681,18 +681,23 @@
* from the page's content. This is triggered by calling
getSecondaryDataUpdates()
* and is used for forward links updates on edit and backlink updates
by jobs.
*
- * @note: custom DataUpdates do not survive serialization of the
ParserOutput!
+ * @note: custom DataUpdates should survive serialization of the
ParserOutput!
* This is especially relevant when using a cached ParserOutput for
updating
* the database, as WikiPage does if $wgAjaxStashEdit is enabled. For
this
- * reason, ApiStashEdit will skip any ParserOutput that has custom
DataUpdates.
+ * reason, ApiStashEdit will skip any ParserOutput that has custom
DataUpdates
+ * that are not serializable. Use LazyDataUpdate instead of DataUpdate
classes.
*
* @since 1.20
*
- * @param DataUpdate $update
+ * @param DataUpdate|LazyDataUpdate $update
*/
- public function addSecondaryDataUpdate( DataUpdate $update ) {
- $this->mSecondaryDataUpdates[] = $update;
- $this->mCustomDataUpdateCount = count(
$this->mSecondaryDataUpdates );
+ public function addSecondaryDataUpdate( $update ) {
+ if ( $update instanceof DataUpdate || $update instanceof
LazyDataUpdate ) {
+ $this->mSecondaryDataUpdates[] = $update;
+ $this->mCustomDataUpdateCount = count(
$this->mSecondaryDataUpdates );
+ } else {
+ throw new Exception( "Expected DataUpdate or
LazyDataUpdate." );
+ }
}
/**
@@ -702,9 +707,27 @@
* @see __sleep()
*
* @return bool
+ * @since 1.25
*/
public function hasCustomDataUpdates() {
return ( $this->mCustomDataUpdateCount > 0 );
+ }
+
+ /**
+ * Check if all secondary updates are either implicit or serializable
+ *
+ * This is mostly for use by ApiEditStash
+ *
+ * @return bool
+ * @since 1.25
+ */
+ public function areSecondaryUpdatesSerializable() {
+ foreach ( $this->mSecondaryDataUpdates as $update ) {
+ if ( ! $update instanceof LazyDataUpdate ) {
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -735,14 +758,20 @@
// NOTE: This happens when mSecondaryDataUpdates are
lost during serialization
// (see __sleep below). After (un)serialization,
getSecondaryDataUpdates()
// has no defined behavior in that case, and should
throw an exception.
- throw new MWException( 'getSecondaryDataUpdates() must
not be called on ParserOutput restored from serialization.' );
+ throw new MWException( 'ParserOutput derived from
unserialization with unserializable data updates.' );
}
- // NOTE: ApiStashEdit knows about this "magic" update object.
If this goes away,
- // ApiStashEdit::buildStashValue needs to be adjusted.
- $linksUpdate = new LinksUpdate( $title, $this, $recursive );
+ $updates = array();
+ foreach ( $this->mSecondaryDataUpdates as $update ) {
+ if ( $update instanceof LazyDataUpdate ) {
+ $updates[] = $update->resolve( $title, $this );
+ } else {
+ $updates[] = $update;
+ }
+ }
+ $updates[] = new LinksUpdate( $title, $this, $recursive );
- return array_merge( $this->mSecondaryDataUpdates, array(
$linksUpdate ) );
+ return $updates;
}
/**
@@ -889,14 +918,17 @@
return wfSetVar( $this->mPreventClickjacking, $flag );
}
- /**
- * Save space for serialization by removing useless values
- * @return array
- */
- public function __sleep() {
+ function __sleep() {
+ // Filter out updates that are not designed to be serializable.
+ // The getSecondaryDataUpdates() method knows when this
happened.
+ $this->mSecondaryDataUpdates = array_filter(
+ $this->mSecondaryDataUpdates,
+ function ( $u ) { return $u instanceof LazyDataUpdate; }
+ );
+
return array_diff(
array_keys( get_object_vars( $this ) ),
- array( 'mSecondaryDataUpdates', 'mParseStartTime' )
+ array( 'mParseStartTime' ) // useless
);
}
}
--
To view, visit https://gerrit.wikimedia.org/r/184463
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9499aaf2e8501a0db8a24e244cacd9a65518a7b2
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits