diff --git a/services/web/app/src/Features/Compile/ClsiManager.js b/services/web/app/src/Features/Compile/ClsiManager.js index 3c09b003ae..fb06b19c0a 100644 --- a/services/web/app/src/Features/Compile/ClsiManager.js +++ b/services/web/app/src/Features/Compile/ClsiManager.js @@ -45,6 +45,13 @@ const ClsiManager = { { ...options, syncType: 'full' }, callback ) + } else if (status === 'unavailable') { + return ClsiManager.sendRequestOnce( + projectId, + userId, + { ...options, syncType: 'full', forceNewClsiServer: true }, + callback + ) } callback(null, status, ...result) } @@ -173,6 +180,22 @@ const ClsiManager = { if (options == null) { options = {} } + if (options.forceNewClsiServer) { + // Clear clsi cookie, then try again + return ClsiCookieManager.clearServerId(projectId, err => { + if (err) { + return callback(err) + } + options.forceNewClsiServer = false // backend has now been reset + return ClsiManager._sendBuiltRequest( + projectId, + userId, + req, + options, + callback + ) + }) + } ClsiFormatChecker.checkRecoursesForProblems( req.compile != null ? req.compile.resources : undefined, (err, validationProblems) => { @@ -434,6 +457,8 @@ const ClsiManager = { callback(null, { compile: { status: 'conflict' } }) } else if (response.statusCode === 423) { callback(null, { compile: { status: 'compile-in-progress' } }) + } else if (response.statusCode === 503) { + callback(null, { compile: { status: 'unavailable' } }) } else { callback( new OError({ diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 1d550675f3..0c3290053b 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/services/web/app/views/project/editor/pdf.pug @@ -285,6 +285,10 @@ div.full-size.pdf(ng-controller="PdfController") strong #{translate("server_error")} span #{translate("clsi_maintenance")} + .alert.alert-danger(ng-show="pdf.clsiUnavailable") + strong #{translate("server_error")} + span #{translate("clsi_unavailable")} + .alert.alert-danger(ng-show="pdf.tooRecentlyCompiled") strong #{translate("server_error")} span #{translate("too_recently_compiled")} diff --git a/services/web/frontend/js/ide/pdf/controllers/PdfController.js b/services/web/frontend/js/ide/pdf/controllers/PdfController.js index a15fa891ec..3c0eb382f2 100644 --- a/services/web/frontend/js/ide/pdf/controllers/PdfController.js +++ b/services/web/frontend/js/ide/pdf/controllers/PdfController.js @@ -462,6 +462,9 @@ App.controller('PdfController', function( } else if (response.status === 'clsi-maintenance') { $scope.pdf.view = 'errors' $scope.pdf.clsiMaintenance = true + } else if (response.status === 'unavailable') { + $scope.pdf.view = 'errors' + $scope.pdf.clsiUnavailable = true } else if (response.status === 'too-recently-compiled') { $scope.pdf.view = 'errors' $scope.pdf.tooRecentlyCompiled = true diff --git a/services/web/test/unit/src/Compile/ClsiManagerTests.js b/services/web/test/unit/src/Compile/ClsiManagerTests.js index fc9b79da07..f040e8015e 100644 --- a/services/web/test/unit/src/Compile/ClsiManagerTests.js +++ b/services/web/test/unit/src/Compile/ClsiManagerTests.js @@ -214,6 +214,50 @@ describe('ClsiManager', function() { }) }) + describe('with an unavailable response', function() { + beforeEach(function() { + this.ClsiManager.sendRequestOnce = sinon.stub() + this.ClsiManager.sendRequestOnce + .withArgs(this.project_id, this.user_id, { + syncType: 'full', + forceNewClsiServer: true + }) + .callsArgWith(3, null, (this.status = 'success')) + this.ClsiManager.sendRequestOnce + .withArgs(this.project_id, this.user_id, {}) + .callsArgWith(3, null, 'unavailable') + this.ClsiManager.sendRequest( + this.project_id, + this.user_id, + {}, + this.callback + ) + }) + + it('should call the sendRequestOnce method twice', function() { + this.ClsiManager.sendRequestOnce.calledTwice.should.equal(true) + }) + + it('should call the sendRequestOnce method with forceNewClsiServer:true', function() { + this.ClsiManager.sendRequestOnce + .calledWith(this.project_id, this.user_id, { + forceNewClsiServer: true, + syncType: 'full' + }) + .should.equal(true) + }) + + it('should call the sendRequestOnce method without forceNewClsiServer:true', function() { + this.ClsiManager.sendRequestOnce + .calledWith(this.project_id, this.user_id, {}) + .should.equal(true) + }) + + it('should call the callback with a success status', function() { + this.callback.calledWith(null, this.status).should.equal(true) + }) + }) + describe('when the resources fail the precompile check', function() { beforeEach(function() { this.ClsiFormatChecker.checkRecoursesForProblems = sinon