jenkins-bot has submitted this change and it was merged.

Change subject: Add a request timeout before the cpu timeout
......................................................................


Add a request timeout before the cpu timeout

Change-Id: If4a4208830fe0041994b5cfb9df5a87ef83c8807
---
M api/routes.js
1 file changed, 61 insertions(+), 43 deletions(-)

Approvals:
  Subramanya Sastry: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/api/routes.js b/api/routes.js
index c7cd818..3214573 100644
--- a/api/routes.js
+++ b/api/routes.js
@@ -35,6 +35,16 @@
 
 // Helpers
 
+// Should be less than the CPU_TIMEOUT
+var REQ_TIMEOUT = 4 * 60 * 1000;  // 4 minutes
+function timeoutResp( env, err ) {
+       if ( err instanceof Promise.TimeoutError ) {
+               err = new Error("Request timed out.");
+               err.stack = null;
+       }
+       env.log("fatal/request", err);
+}
+
 var CPU_TIMEOUT = 5 * 60 * 1000;  // 5 minutes
 var cpuTimeout = function( p, res ) {
        return new Promise(function( resolve, reject ) {
@@ -72,6 +82,12 @@
                        }
                });
        });
+};
+
+var rtResponse = function( env, req, res, data ) {
+       apiUtils.setHeader( res, env, 'X-Parsoid-Performance', 
env.getPerformanceHeader() );
+       apiUtils.renderResponse( res, env, "roundtrip", data );
+       env.log( "info", "completed parsing in", env.performance.duration, "ms" 
);
 };
 
 var roundTripDiff = function( env, req, res, selser, doc ) {
@@ -115,19 +131,13 @@
 
                var patch = Diff.convertChangesToXML( Diff.diffLines(src, out) 
);
 
-               apiUtils.setHeader(res, env, 'X-Parsoid-Performance', 
env.getPerformanceHeader());
-
-               apiUtils.renderResponse(res, env, "roundtrip", {
+               return {
                        headers: headNodes,
                        bodyNodes: bodyNodes,
                        htmlSpeChars: htmlSpeChars,
                        patch: patch,
                        reqUrl: req.url
-               });
-
-               env.log("info", "completed parsing in", 
env.performance.duration, "ms");
-       }).catch(function( err ) {
-               env.log("fatal/request", err);
+               };
        });
 };
 
@@ -178,8 +188,6 @@
                return Promise.promisify( pipeline.parse, false, pipeline )(
                        env, env.page.src, expansions
                );
-       }).catch(function( err ) {
-               env.log("fatal/request", err);
        });
 };
 
@@ -191,7 +199,7 @@
                // allow cross-domain requests (CORS) so that parsoid service
                // can be used by third-party sites
                apiUtils.setHeader(res, env, 'Access-Control-Allow-Origin',
-                                          env.conf.parsoid.allowCORS );
+                                                  env.conf.parsoid.allowCORS );
        }
 
        var out = [];
@@ -217,14 +225,13 @@
                return Promise.promisify( serializer.serializeDOM, false, 
serializer )(
                        doc.body, function( chunk ) { out.push( chunk ); }, 
false
                );
-       }).then(function() {
+       }).timeout( REQ_TIMEOUT ).then(function() {
                apiUtils.setHeader(res, env, 'Content-Type', 'text/x-mediawiki; 
charset=UTF-8');
                apiUtils.setHeader(res, env, 'X-Parsoid-Performance', 
env.getPerformanceHeader());
                apiUtils.endResponse(res, env, out.join(''));
        });
-       return cpuTimeout(p, res).catch(function( err ) {
-               env.log("fatal/request", err);
-       });
+       return cpuTimeout( p, res )
+               .catch( timeoutResp.bind(null, env) );
 };
 
 var wt2html = function( req, res, wt, v2 ) {
@@ -275,20 +282,22 @@
                                resolve( doc );
                        });
                        parser.processToplevelDoc( wt );
-               }).then( sendRes );
+               });
        }
 
        function parsePageWithOldid() {
-               if ( !req.headers.cookie ) {
-                       apiUtils.setHeader(res, env, 'Cache-Control', 
's-maxage=2592000');
-               } else {
-                       // Don't cache requests with a session
-                       apiUtils.setHeader(res, env, 'Cache-Control', 
'private,no-cache,s-maxage=0');
-               }
-               // Indicate the MediaWiki revision in a header as well for
-               // ease of extraction in clients.
-               apiUtils.setHeader(res, env, 'content-revision-id', oldid);
-               return parse( env, req, res ).then( sendRes );
+               return parse( env, req, res ).then(function( doc ) {
+                       if ( !req.headers.cookie ) {
+                               apiUtils.setHeader(res, env, 'Cache-Control', 
's-maxage=2592000');
+                       } else {
+                               // Don't cache requests with a session
+                               apiUtils.setHeader(res, env, 'Cache-Control', 
'private,no-cache,s-maxage=0');
+                       }
+                       // Indicate the MediaWiki revision in a header as well 
for
+                       // ease of extraction in clients.
+                       apiUtils.setHeader(res, env, 'content-revision-id', 
oldid);
+                       return doc;
+               });
        }
 
        function redirectToOldid() {
@@ -328,16 +337,19 @@
        }
 
        if ( wt ) {
-               p = p.then( parseWt );
+               p = p.then( parseWt )
+                       .timeout( REQ_TIMEOUT )
+                       .then(sendRes);
        } else if ( oldid ) {
-               p = p.then( parsePageWithOldid );
+               p = p.then( parsePageWithOldid )
+                       .timeout( REQ_TIMEOUT )
+                       .then(sendRes);
        } else {
                p = p.then( redirectToOldid );
        }
 
-       return cpuTimeout(p, res).catch(function( err ) {
-               env.log("fatal/request", err);
-       });
+       return cpuTimeout( p, res )
+               .catch( timeoutResp.bind(null, env) );
 };
 
 
@@ -488,10 +500,12 @@
                parse.bind( null, env, req, res )
        ).then(
                roundTripDiff.bind( null, env, req, res, false )
+       ).timeout( REQ_TIMEOUT ).then(
+               rtResponse.bind( null, env, req, res )
        );
-       cpuTimeout(p, res).catch(function(err) {
-               env.log("fatal/request", err);
-       });
+
+       cpuTimeout( p, res )
+               .catch( timeoutResp.bind(null, env) );
 };
 
 // Round-trip article testing with newline stripping for editor-created HTML
@@ -511,10 +525,12 @@
                // strip newlines from the html
                var html = doc.innerHTML.replace(/[\r\n]/g, '');
                return roundTripDiff( env, req, res, false, DU.parseHTML(html) 
);
-       });
-       cpuTimeout(p, res).catch(function(err) {
-               env.log("fatal/request", err);
-       });
+       }).timeout( REQ_TIMEOUT ).then(
+               rtResponse.bind( null, env, req, res )
+       );
+
+       cpuTimeout( p, res )
+               .catch( timeoutResp.bind(null, env) );
 };
 
 // Round-trip article testing with selser over re-parsed HTML.
@@ -534,10 +550,12 @@
                var comment = doc.createComment('rtSelserEditTestComment');
                doc.body.appendChild(comment);
                return roundTripDiff( env, req, res, true, doc );
-       });
-       cpuTimeout(p, res).catch(function(err) {
-               env.log("fatal/request", err);
-       });
+       }).timeout( REQ_TIMEOUT ).then(
+               rtResponse.bind( null, env, req, res )
+       );
+
+       cpuTimeout( p, res )
+               .catch( timeoutResp.bind(null, env) );
 };
 
 // Form-based round-tripping for manual testing
@@ -559,7 +577,7 @@
        });
        parse( env, req, res ).then(
                roundTripDiff.bind( null, env, req, res, false )
-       ).catch(function(err) {
+       ).then( rtResponse ).catch(function(err) {
                env.log("fatal/request", err);
        });
 };

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

Gerrit-MessageType: merged
Gerrit-Change-Id: If4a4208830fe0041994b5cfb9df5a87ef83c8807
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/services/parsoid
Gerrit-Branch: master
Gerrit-Owner: Arlolra <abrea...@wikimedia.org>
Gerrit-Reviewer: Arlolra <abrea...@wikimedia.org>
Gerrit-Reviewer: Cscott <canan...@wikimedia.org>
Gerrit-Reviewer: Marcoil <marc...@wikimedia.org>
Gerrit-Reviewer: Subramanya Sastry <ssas...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to