Realtime Preview: disable if average response time is very slow

$wgWikiEditorRealtimeDisableDuration is introduced which allows
sysadmins to control the average time after which Realtime Preview
should be disabled. For now, this shows a simple error message that is
intentionally not localized. In a future patch, we will force the
user into a 'manual preview' workflow. See T304568 for more.

Bug: T302282
Change-Id: I2f01eef19fe81c19efedcc0073a28884f0055359
This commit is contained in:
MusikAnimal 2022-03-24 20:19:30 -04:00
parent cdd01171cc
commit f1a2ba96eb
3 changed files with 34 additions and 0 deletions

View file

@ -432,6 +432,10 @@
"WikiEditorRealtimePreviewDebounce": { "WikiEditorRealtimePreviewDebounce": {
"description": "Debounce time in milliseconds for the Realtime Preview feature.", "description": "Debounce time in milliseconds for the Realtime Preview feature.",
"value": 2500 "value": 2500
},
"WikiEditorRealtimeDisableDuration": {
"description": "Average number of milliseconds after which to automatically disable Realtime Preview.",
"value": 10000
} }
}, },
"manifest_version": 2 "manifest_version": 2

View file

@ -358,6 +358,7 @@ class Hooks implements
'magicWords' => self::getMagicWords(), 'magicWords' => self::getMagicWords(),
'signature' => self::getSignatureMessage( $context ), 'signature' => self::getSignatureMessage( $context ),
'realtimeDebounce' => $config->get( 'WikiEditorRealtimePreviewDebounce' ), 'realtimeDebounce' => $config->get( 'WikiEditorRealtimePreviewDebounce' ),
'realtimeDisableDuration' => $config->get( 'WikiEditorRealtimeDisableDuration' ),
]; ];
} }

View file

@ -26,6 +26,8 @@ function RealtimePreview() {
// Used to ensure we wait for a response before making new requests. // Used to ensure we wait for a response before making new requests.
this.isPreviewing = false; this.isPreviewing = false;
this.previewPending = false; this.previewPending = false;
// Used to average response times and automatically disable realtime preview if it's very slow.
this.responseTimes = [];
} }
/** /**
@ -131,6 +133,30 @@ RealtimePreview.prototype.showError = function ( $msg ) {
this.errorLayout.toggle( true ); this.errorLayout.toggle( true );
}; };
/**
* @private
* @param {number} time
*/
RealtimePreview.prototype.checkResponseTimes = function ( time ) {
this.responseTimes.push( Date.now() - time );
if ( this.responseTimes.length < 3 ) {
return;
}
var totalResponseTime = this.responseTimes.reduce( function ( a, b ) {
return a + b;
}, 0 );
if ( ( totalResponseTime / this.responseTimes.length ) > this.configData.realtimeDisableDuration ) {
// TODO: switch to the 'manual preview' workflow once designs/behaviour is finalized.
this.showError(
$( '<div>' ).text( '[PLACEHOLDER] Realtime preview is too slow' )
);
}
this.responseTimes.shift();
};
/** /**
* @private * @private
*/ */
@ -147,6 +173,8 @@ RealtimePreview.prototype.doRealtimePreview = function () {
var loadingSelectors = this.pagePreview.getLoadingSelectors(); var loadingSelectors = this.pagePreview.getLoadingSelectors();
loadingSelectors.push( '.ext-WikiEditor-realtimepreview-preview' ); loadingSelectors.push( '.ext-WikiEditor-realtimepreview-preview' );
this.errorLayout.toggle( false ); this.errorLayout.toggle( false );
var time = Date.now();
this.pagePreview.doPreview( { this.pagePreview.doPreview( {
$previewNode: this.$previewNode, $previewNode: this.$previewNode,
$spinnerNode: false, $spinnerNode: false,
@ -157,6 +185,7 @@ RealtimePreview.prototype.doRealtimePreview = function () {
}.bind( this ) ).always( function () { }.bind( this ) ).always( function () {
this.twoPaneLayout.getPane2().removeClass( 'ext-WikiEditor-twopanes-loading' ); this.twoPaneLayout.getPane2().removeClass( 'ext-WikiEditor-twopanes-loading' );
this.isPreviewing = false; this.isPreviewing = false;
this.checkResponseTimes( time );
if ( this.previewPending ) { if ( this.previewPending ) {
this.previewPending = false; this.previewPending = false;