Merge pull request #7867 from overleaf/jpa-compile-group

[web] pass compileGroup to clsi-lb

GitOrigin-RevId: c15adbff27e702b3e0f29be5b57f7a9520d8d02f
This commit is contained in:
Jakob Ackermann 2022-05-13 10:35:31 +01:00 committed by Copybot
parent 8157616f85
commit 52073a13a9
12 changed files with 245 additions and 142 deletions

View file

@ -12,6 +12,7 @@
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/ */
let rclient_secondary let rclient_secondary
const { URL, URLSearchParams } = require('url')
const OError = require('@overleaf/o-error') const OError = require('@overleaf/o-error')
const Settings = require('@overleaf/settings') const Settings = require('@overleaf/settings')
const request = require('request').defaults({ timeout: 30 * 1000 }) const request = require('request').defaults({ timeout: 30 * 1000 })
@ -38,7 +39,7 @@ module.exports = function (backendGroup) {
} }
}, },
_getServerId(project_id, user_id, callback) { _getServerId(project_id, user_id, compileGroup, callback) {
if (callback == null) { if (callback == null) {
callback = function () {} callback = function () {}
} }
@ -52,6 +53,7 @@ module.exports = function (backendGroup) {
return this._populateServerIdViaRequest( return this._populateServerIdViaRequest(
project_id, project_id,
user_id, user_id,
compileGroup,
callback callback
) )
} else { } else {
@ -61,12 +63,15 @@ module.exports = function (backendGroup) {
) )
}, },
_populateServerIdViaRequest(project_id, user_id, callback) { _populateServerIdViaRequest(project_id, user_id, compileGroup, callback) {
if (callback == null) { if (callback == null) {
callback = function () {} callback = function () {}
} }
const url = `${Settings.apis.clsi.url}/project/${project_id}/status` const u = new URL(
request.post(url, (err, res, body) => { `${Settings.apis.clsi.url}/project/${project_id}/status`
)
u.search = new URLSearchParams({ compileGroup }).toString()
request.post(u.href, (err, res, body) => {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting initial server id for project', { OError.tag(err, 'error getting initial server id for project', {
project_id, project_id,
@ -76,6 +81,7 @@ module.exports = function (backendGroup) {
this.setServerId( this.setServerId(
project_id, project_id,
user_id, user_id,
compileGroup,
res, res,
null, null,
function (err, serverId) { function (err, serverId) {
@ -100,11 +106,11 @@ module.exports = function (backendGroup) {
return cookies != null ? cookies[Settings.clsiCookie.key] : undefined return cookies != null ? cookies[Settings.clsiCookie.key] : undefined
}, },
checkIsLoadSheddingEvent(clsiserverid) { checkIsLoadSheddingEvent(clsiserverid, compileGroup) {
request.get( request.get(
{ {
url: `${Settings.apis.clsi.url}/instance-state`, url: `${Settings.apis.clsi.url}/instance-state`,
qs: { clsiserverid }, qs: { clsiserverid, compileGroup },
}, },
(err, res, body) => { (err, res, body) => {
if (err) { if (err) {
@ -123,7 +129,14 @@ module.exports = function (backendGroup) {
) )
}, },
setServerId(project_id, user_id, response, previous, callback) { setServerId(
project_id,
user_id,
compileGroup,
response,
previous,
callback
) {
if (callback == null) { if (callback == null) {
callback = function () {} callback = function () {}
} }
@ -143,7 +156,7 @@ module.exports = function (backendGroup) {
// Initial assignment of a user+project or after clearing cache. // Initial assignment of a user+project or after clearing cache.
Metrics.inc('clsi-lb-assign-initial-backend') Metrics.inc('clsi-lb-assign-initial-backend')
} else { } else {
this.checkIsLoadSheddingEvent(previous) this.checkIsLoadSheddingEvent(previous, compileGroup)
} }
if (rclient_secondary != null) { if (rclient_secondary != null) {
this._setServerIdInRedis( this._setServerIdInRedis(
@ -181,27 +194,32 @@ module.exports = function (backendGroup) {
return rclient.del(this.buildKey(project_id, user_id), callback) return rclient.del(this.buildKey(project_id, user_id), callback)
}, },
getCookieJar(project_id, user_id, callback) { getCookieJar(project_id, user_id, compileGroup, callback) {
if (callback == null) { if (callback == null) {
callback = function () {} callback = function () {}
} }
if (!clsiCookiesEnabled) { if (!clsiCookiesEnabled) {
return callback(null, request.jar(), undefined) return callback(null, request.jar(), undefined)
} }
return this._getServerId(project_id, user_id, (err, serverId) => { return this._getServerId(
if (err != null) { project_id,
OError.tag(err, 'error getting server id', { user_id,
project_id, compileGroup,
}) (err, serverId) => {
return callback(err) if (err != null) {
OError.tag(err, 'error getting server id', {
project_id,
})
return callback(err)
}
const serverCookie = request.cookie(
`${Settings.clsiCookie.key}=${serverId}`
)
const jar = request.jar()
jar.setCookie(serverCookie, Settings.apis.clsi.url)
return callback(null, jar, serverId)
} }
const serverCookie = request.cookie( )
`${Settings.clsiCookie.key}=${serverId}`
)
const jar = request.jar()
jar.setCookie(serverCookie, Settings.apis.clsi.url)
return callback(null, jar, serverId)
})
}, },
} }
} }

View file

@ -4,7 +4,7 @@ const request = require('request')
const ProjectGetter = require('../Project/ProjectGetter') const ProjectGetter = require('../Project/ProjectGetter')
const ProjectEntityHandler = require('../Project/ProjectEntityHandler') const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
const logger = require('@overleaf/logger') const logger = require('@overleaf/logger')
const { URL } = require('url') const { URL, URLSearchParams } = require('url')
const OError = require('@overleaf/o-error') const OError = require('@overleaf/o-error')
const ClsiCookieManager = require('./ClsiCookieManager')( const ClsiCookieManager = require('./ClsiCookieManager')(
@ -122,8 +122,9 @@ const ClsiManager = {
if (options == null) { if (options == null) {
options = {} options = {}
} }
const { compileGroup } = options
const compilerUrl = this._getCompilerUrl( const compilerUrl = this._getCompilerUrl(
options.compileGroup, compileGroup,
projectId, projectId,
userId, userId,
'compile/stop' 'compile/stop'
@ -132,18 +133,15 @@ const ClsiManager = {
url: compilerUrl, url: compilerUrl,
method: 'POST', method: 'POST',
} }
ClsiManager._makeRequest(projectId, userId, opts, callback) ClsiManager._makeRequest(projectId, userId, compileGroup, opts, callback)
}, },
deleteAuxFiles(projectId, userId, options, clsiserverid, callback) { deleteAuxFiles(projectId, userId, options, clsiserverid, callback) {
if (options == null) { if (options == null) {
options = {} options = {}
} }
const compilerUrl = this._getCompilerUrl( const { compileGroup } = options
options.compileGroup, const compilerUrl = this._getCompilerUrl(compileGroup, projectId, userId)
projectId,
userId
)
const opts = { const opts = {
url: compilerUrl, url: compilerUrl,
method: 'DELETE', method: 'DELETE',
@ -151,6 +149,7 @@ const ClsiManager = {
ClsiManager._makeRequestWithClsiServerId( ClsiManager._makeRequestWithClsiServerId(
projectId, projectId,
userId, userId,
compileGroup,
opts, opts,
clsiserverid, clsiserverid,
clsiErr => { clsiErr => {
@ -274,13 +273,14 @@ const ClsiManager = {
_makeRequestWithClsiServerId( _makeRequestWithClsiServerId(
projectId, projectId,
userId, userId,
compileGroup,
opts, opts,
clsiserverid, clsiserverid,
callback callback
) { ) {
if (clsiserverid) { if (clsiserverid) {
// ignore cookies and newBackend, go straight to the clsi node // ignore cookies and newBackend, go straight to the clsi node
opts.qs = Object.assign({ clsiserverid }, opts.qs) opts.qs = Object.assign({ compileGroup, clsiserverid }, opts.qs)
request(opts, (err, response, body) => { request(opts, (err, response, body) => {
if (err) { if (err) {
return callback( return callback(
@ -290,11 +290,11 @@ const ClsiManager = {
callback(null, response, body) callback(null, response, body)
}) })
} else { } else {
ClsiManager._makeRequest(projectId, userId, opts, callback) ClsiManager._makeRequest(projectId, userId, compileGroup, opts, callback)
} }
}, },
_makeRequest(projectId, userId, opts, callback) { _makeRequest(projectId, userId, compileGroup, opts, callback) {
async.series( async.series(
{ {
currentBackend(cb) { currentBackend(cb) {
@ -302,6 +302,7 @@ const ClsiManager = {
ClsiCookieManager.getCookieJar( ClsiCookieManager.getCookieJar(
projectId, projectId,
userId, userId,
compileGroup,
(err, jar, clsiServerId) => { (err, jar, clsiServerId) => {
if (err != null) { if (err != null) {
return callback( return callback(
@ -327,6 +328,7 @@ const ClsiManager = {
ClsiCookieManager.setServerId( ClsiCookieManager.setServerId(
projectId, projectId,
userId, userId,
compileGroup,
response, response,
clsiServerId, clsiServerId,
(err, newClsiServerId) => { (err, newClsiServerId) => {
@ -361,6 +363,7 @@ const ClsiManager = {
ClsiManager._makeNewBackendRequest( ClsiManager._makeNewBackendRequest(
projectId, projectId,
userId, userId,
compileGroup,
opts, opts,
(err, response, body) => { (err, response, body) => {
if (err != null) { if (err != null) {
@ -407,7 +410,7 @@ const ClsiManager = {
) )
}, },
_makeNewBackendRequest(projectId, userId, baseOpts, callback) { _makeNewBackendRequest(projectId, userId, compileGroup, baseOpts, callback) {
if (Settings.apis.clsi_new == null || Settings.apis.clsi_new.url == null) { if (Settings.apis.clsi_new == null || Settings.apis.clsi_new.url == null) {
return callback() return callback()
} }
@ -421,6 +424,7 @@ const ClsiManager = {
NewBackendCloudClsiCookieManager.getCookieJar( NewBackendCloudClsiCookieManager.getCookieJar(
projectId, projectId,
userId, userId,
compileGroup,
(err, jar, clsiServerId) => { (err, jar, clsiServerId) => {
if (err != null) { if (err != null) {
return callback( return callback(
@ -444,6 +448,7 @@ const ClsiManager = {
NewBackendCloudClsiCookieManager.setServerId( NewBackendCloudClsiCookieManager.setServerId(
projectId, projectId,
userId, userId,
compileGroup,
response, response,
clsiServerId, clsiServerId,
err => { err => {
@ -463,15 +468,15 @@ const ClsiManager = {
}, },
_getCompilerUrl(compileGroup, projectId, userId, action) { _getCompilerUrl(compileGroup, projectId, userId, action) {
const host = Settings.apis.clsi.url const u = new URL(`/project/${projectId}`, Settings.apis.clsi.url)
let path = `/project/${projectId}`
if (userId != null) { if (userId != null) {
path += `/user/${userId}` u.pathname += `/user/${userId}`
} }
if (action != null) { if (action != null) {
path += `/${action}` u.pathname += `/${action}`
} }
return `${host}${path}` u.search = new URLSearchParams({ compileGroup }).toString()
return u.href
}, },
_postToClsi(projectId, userId, req, compileGroup, callback) { _postToClsi(projectId, userId, req, compileGroup, callback) {
@ -489,16 +494,21 @@ const ClsiManager = {
ClsiManager._makeRequest( ClsiManager._makeRequest(
projectId, projectId,
userId, userId,
compileGroup,
opts, opts,
(err, response, body, clsiServerId) => { (err, response, body, clsiServerId) => {
if (err != null) { if (err != null) {
return callback( return callback(
new OError('failed to make request to CLSI', { new OError(
projectId, 'failed to make request to CLSI',
userId, {
compileOptions: req.compile.options, projectId,
rootResourcePath: req.compile.rootResourcePath, userId,
}) compileOptions: req.compile.options,
rootResourcePath: req.compile.rootResourcePath,
},
err
)
) )
} }
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
@ -655,9 +665,18 @@ const ClsiManager = {
) )
}, },
getOutputFileStream(projectId, userId, buildId, outputFilePath, callback) { getOutputFileStream(
projectId,
userId,
compileGroup,
clsiServerId,
buildId,
outputFilePath,
callback
) {
const url = `${Settings.apis.clsi.url}/project/${projectId}/user/${userId}/build/${buildId}/output/${outputFilePath}` const url = `${Settings.apis.clsi.url}/project/${projectId}/user/${userId}/build/${buildId}/output/${outputFilePath}`
ClsiCookieManager.getCookieJar(projectId, userId, (err, jar) => { // TODO(das7pad): remove one week after landing frontend changes.
ClsiCookieManager.getCookieJar(projectId, userId, '', (err, jar) => {
if (err != null) { if (err != null) {
return callback( return callback(
OError.tag(err, 'Failed to get cookie jar', { OError.tag(err, 'Failed to get cookie jar', {
@ -669,6 +688,10 @@ const ClsiManager = {
) )
} }
const options = { url, method: 'GET', timeout: 60 * 1000, jar } const options = { url, method: 'GET', timeout: 60 * 1000, jar }
if (clsiServerId) {
options.qs = { compileGroup, clsiserverid: clsiServerId }
delete options.jar
}
const readStream = request(options) const readStream = request(options)
callback(null, readStream) callback(null, readStream)
}) })
@ -863,6 +886,7 @@ const ClsiManager = {
}, },
wordCount(projectId, userId, file, options, clsiserverid, callback) { wordCount(projectId, userId, file, options, clsiserverid, callback) {
const { compileGroup } = options
ClsiManager._buildRequest(projectId, options, (err, req) => { ClsiManager._buildRequest(projectId, options, (err, req) => {
if (err != null) { if (err != null) {
return callback( return callback(
@ -874,7 +898,7 @@ const ClsiManager = {
} }
const filename = file || req.compile.rootResourcePath const filename = file || req.compile.rootResourcePath
const wordCountUrl = ClsiManager._getCompilerUrl( const wordCountUrl = ClsiManager._getCompilerUrl(
options.compileGroup, compileGroup,
projectId, projectId,
userId, userId,
'wordcount' 'wordcount'
@ -891,6 +915,7 @@ const ClsiManager = {
ClsiManager._makeRequestWithClsiServerId( ClsiManager._makeRequestWithClsiServerId(
projectId, projectId,
userId, userId,
compileGroup,
opts, opts,
clsiserverid, clsiserverid,
(err, response, body) => { (err, response, body) => {

View file

@ -336,6 +336,7 @@ module.exports = CompileController = {
const limits = { const limits = {
compileGroup: compileGroup:
(req.body != null ? req.body.compileGroup : undefined) || (req.body != null ? req.body.compileGroup : undefined) ||
req.query?.compileGroup ||
Settings.defaultFeatures.compileGroup, Settings.defaultFeatures.compileGroup,
} }
return CompileController.proxyToClsiWithLimits( return CompileController.proxyToClsiWithLimits(
@ -489,59 +490,64 @@ module.exports = CompileController = {
if (next == null) { if (next == null) {
next = function () {} next = function () {}
} }
_getPersistenceOptions(req, project_id, (err, persistenceOptions) => { _getPersistenceOptions(
let qs req,
if (err != null) { project_id,
OError.tag(err, 'error getting cookie jar for clsi request') limits.compileGroup,
return next(err) (err, persistenceOptions) => {
} let qs
// expand any url parameter passed in as {url:..., qs:...} if (err != null) {
if (typeof url === 'object') { OError.tag(err, 'error getting cookie jar for clsi request')
;({ url, qs } = url) return next(err)
}
const compilerUrl = Settings.apis.clsi.url
url = `${compilerUrl}${url}`
const oneMinute = 60 * 1000
// the base request
const options = {
url,
method: req.method,
timeout: oneMinute,
...persistenceOptions,
}
// add any provided query string
if (qs != null) {
options.qs = Object.assign(options.qs || {}, qs)
}
// if we have a build parameter, pass it through to the clsi
if (
(req.query != null ? req.query.pdfng : undefined) &&
(req.query != null ? req.query.build : undefined) != null
) {
// only for new pdf viewer
if (options.qs == null) {
options.qs = {}
} }
options.qs.build = req.query.build // expand any url parameter passed in as {url:..., qs:...}
} if (typeof url === 'object') {
// if we are byte serving pdfs, pass through If-* and Range headers ;({ url, qs } = url)
// do not send any others, there's a proxying loop if Host: is passed! }
if (req.query != null ? req.query.pdfng : undefined) { const compilerUrl = Settings.apis.clsi.url
const newHeaders = {} url = `${compilerUrl}${url}`
for (const h in req.headers) { const oneMinute = 60 * 1000
const v = req.headers[h] // the base request
if (/^(If-|Range)/i.test(h)) { const options = {
newHeaders[h] = req.headers[h] url,
method: req.method,
timeout: oneMinute,
...persistenceOptions,
}
// add any provided query string
if (qs != null) {
options.qs = Object.assign(options.qs || {}, qs)
}
// if we have a build parameter, pass it through to the clsi
if (
(req.query != null ? req.query.pdfng : undefined) &&
(req.query != null ? req.query.build : undefined) != null
) {
// only for new pdf viewer
if (options.qs == null) {
options.qs = {}
} }
options.qs.build = req.query.build
} }
options.headers = newHeaders // if we are byte serving pdfs, pass through If-* and Range headers
// do not send any others, there's a proxying loop if Host: is passed!
if (req.query != null ? req.query.pdfng : undefined) {
const newHeaders = {}
for (const h in req.headers) {
const v = req.headers[h]
if (/^(If-|Range)/i.test(h)) {
newHeaders[h] = req.headers[h]
}
}
options.headers = newHeaders
}
const proxy = request(options)
proxy.pipe(res)
return proxy.on('error', error =>
logger.warn({ err: error, url }, 'CLSI proxy error')
)
} }
const proxy = request(options) )
proxy.pipe(res)
return proxy.on('error', error =>
logger.warn({ err: error, url }, 'CLSI proxy error')
)
})
}, },
wordCount(req, res, next) { wordCount(req, res, next) {
@ -568,14 +574,19 @@ module.exports = CompileController = {
}, },
} }
function _getPersistenceOptions(req, projectId, callback) { function _getPersistenceOptions(req, projectId, compileGroup, callback) {
const { clsiserverid } = req.query const { clsiserverid } = req.query
const user_id = SessionManager.getLoggedInUserId(req) const user_id = SessionManager.getLoggedInUserId(req)
if (clsiserverid && typeof clsiserverid === 'string') { if (clsiserverid && typeof clsiserverid === 'string') {
callback(null, { qs: { clsiserverid } }) callback(null, { qs: { clsiserverid, compileGroup } })
} else { } else {
ClsiCookieManager.getCookieJar(projectId, user_id, (err, jar) => { ClsiCookieManager.getCookieJar(
callback(err, { jar }) projectId,
}) user_id,
compileGroup,
(err, jar) => {
callback(err, { jar })
}
)
} }
} }

View file

@ -131,6 +131,8 @@ function _sanitizeData(data) {
source_project_id: data.source_project_id, source_project_id: data.source_project_id,
source_output_file_path: data.source_output_file_path, source_output_file_path: data.source_output_file_path,
build_id: data.build_id, build_id: data.build_id,
clsiServerId: data.clsiServerId,
compileGroup: data.compileGroup,
} }
} }
@ -168,8 +170,12 @@ function _checkAuth(projectId, data, currentUserId, callback) {
function _getFileStream(linkedFileData, userId, callback) { function _getFileStream(linkedFileData, userId, callback) {
callback = _.once(callback) callback = _.once(callback)
const { source_output_file_path: sourceOutputFilePath, build_id: buildId } = const {
linkedFileData source_output_file_path: sourceOutputFilePath,
build_id: buildId,
clsiServerId,
compileGroup,
} = linkedFileData
LinkedFilesHandler.getSourceProject(linkedFileData, (err, project) => { LinkedFilesHandler.getSourceProject(linkedFileData, (err, project) => {
if (err) { if (err) {
return callback(err) return callback(err)
@ -178,6 +184,8 @@ function _getFileStream(linkedFileData, userId, callback) {
ClsiManager.getOutputFileStream( ClsiManager.getOutputFileStream(
sourceProjectId, sourceProjectId,
userId, userId,
compileGroup,
clsiServerId,
buildId, buildId,
sourceOutputFilePath, sourceOutputFilePath,
(err, readStream) => { (err, readStream) => {
@ -203,7 +211,7 @@ function _compileAndGetFileStream(linkedFileData, userId, callback) {
sourceProjectId, sourceProjectId,
userId, userId,
{}, {},
(err, status, outputFiles) => { (err, status, outputFiles, clsiServerId, limits) => {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@ -221,6 +229,8 @@ function _compileAndGetFileStream(linkedFileData, userId, callback) {
ClsiManager.getOutputFileStream( ClsiManager.getOutputFileStream(
sourceProjectId, sourceProjectId,
userId, userId,
limits.compileGroup,
clsiServerId,
buildId, buildId,
sourceOutputFilePath, sourceOutputFilePath,
(err, readStream) => { (err, readStream) => {

View file

@ -94,6 +94,8 @@ export default function FileTreeImportFromProject() {
source_project_id: selectedProject._id, source_project_id: selectedProject._id,
source_output_file_path: selectedProjectOutputFile.path, source_output_file_path: selectedProjectOutputFile.path,
build_id: selectedProjectOutputFile.build, build_id: selectedProjectOutputFile.build,
clsiServerId: selectedProjectOutputFile.clsiServerId,
compileGroup: selectedProjectOutputFile.compileGroup,
}, },
}) })
} else { } else {

View file

@ -31,7 +31,10 @@ export function useProjectOutputFiles(projectId) {
const filteredFiles = data.outputFiles.filter(file => const filteredFiles = data.outputFiles.filter(file =>
file.path.match(/.*\.(pdf|png|jpeg|jpg|gif)/) file.path.match(/.*\.(pdf|png|jpeg|jpg|gif)/)
) )
data.outputFiles.forEach(file => {
file.clsiServerId = data.clsiServerId
file.compileGroup = data.compileGroup
})
setData(filteredFiles.sort(alphabetical)) setData(filteredFiles.sort(alphabetical))
} else { } else {
setError('linked-project-compile-error') setError('linked-project-compile-error')

View file

@ -1,7 +1,7 @@
const topFileTypes = ['bbl', 'gls', 'ind'] const topFileTypes = ['bbl', 'gls', 'ind']
const ignoreFiles = ['output.fls', 'output.fdb_latexmk'] const ignoreFiles = ['output.fls', 'output.fdb_latexmk']
export const buildFileList = (outputFiles, clsiServerId) => { export const buildFileList = (outputFiles, clsiServerId, compileGroup) => {
const files = { top: [], other: [] } const files = { top: [], other: [] }
if (outputFiles) { if (outputFiles) {
@ -10,6 +10,9 @@ export const buildFileList = (outputFiles, clsiServerId) => {
if (clsiServerId) { if (clsiServerId) {
params.set('clsiserverid', clsiServerId) params.set('clsiserverid', clsiServerId)
} }
if (compileGroup) {
params.set('compileGroup', compileGroup)
}
const queryString = params.toString() const queryString = params.toString()

View file

@ -253,7 +253,9 @@ export function LocalCompileProvider({ children }) {
setPdfUrl(result.pdfUrl) setPdfUrl(result.pdfUrl)
} }
setFileList(buildFileList(outputFiles, data.clsiServerId)) setFileList(
buildFileList(outputFiles, data.clsiServerId, data.compileGroup)
)
// handle log files // handle log files
// asynchronous (TODO: cancel on new compile?) // asynchronous (TODO: cancel on new compile?)

View file

@ -67,6 +67,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager._getServerId( return this.ClsiCookieManager._getServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'',
(err, serverId) => { (err, serverId) => {
this.redis.get this.redis.get
.calledWith(`clsiserver:${this.project_id}:${this.user_id}`) .calledWith(`clsiserver:${this.project_id}:${this.user_id}`)
@ -80,11 +81,12 @@ describe('ClsiCookieManager', function () {
it('should _populateServerIdViaRequest if no key is found', function (done) { it('should _populateServerIdViaRequest if no key is found', function (done) {
this.ClsiCookieManager._populateServerIdViaRequest = sinon this.ClsiCookieManager._populateServerIdViaRequest = sinon
.stub() .stub()
.callsArgWith(2) .yields(null)
this.redis.get.callsArgWith(1, null) this.redis.get.callsArgWith(1, null)
return this.ClsiCookieManager._getServerId( return this.ClsiCookieManager._getServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'',
(err, serverId) => { (err, serverId) => {
this.ClsiCookieManager._populateServerIdViaRequest this.ClsiCookieManager._populateServerIdViaRequest
.calledWith(this.project_id, this.user_id) .calledWith(this.project_id, this.user_id)
@ -97,11 +99,12 @@ describe('ClsiCookieManager', function () {
it('should _populateServerIdViaRequest if no key is blank', function (done) { it('should _populateServerIdViaRequest if no key is blank', function (done) {
this.ClsiCookieManager._populateServerIdViaRequest = sinon this.ClsiCookieManager._populateServerIdViaRequest = sinon
.stub() .stub()
.callsArgWith(2) .yields(null)
this.redis.get.callsArgWith(1, null, '') this.redis.get.callsArgWith(1, null, '')
return this.ClsiCookieManager._getServerId( return this.ClsiCookieManager._getServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'',
(err, serverId) => { (err, serverId) => {
this.ClsiCookieManager._populateServerIdViaRequest this.ClsiCookieManager._populateServerIdViaRequest
.calledWith(this.project_id, this.user_id) .calledWith(this.project_id, this.user_id)
@ -125,11 +128,13 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager._populateServerIdViaRequest( return this.ClsiCookieManager._populateServerIdViaRequest(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
(err, serverId) => { (err, serverId) => {
const args = this.ClsiCookieManager.setServerId.args[0] const args = this.ClsiCookieManager.setServerId.args[0]
args[0].should.equal(this.project_id) args[0].should.equal(this.project_id)
args[1].should.equal(this.user_id) args[1].should.equal(this.user_id)
args[2].should.deep.equal(this.response) args[2].should.equal('standard')
args[3].should.deep.equal(this.response)
return done() return done()
} }
) )
@ -139,6 +144,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager._populateServerIdViaRequest( return this.ClsiCookieManager._populateServerIdViaRequest(
this.project_id, this.project_id,
this.user_id, this.user_id,
'',
(err, serverId) => { (err, serverId) => {
serverId.should.equal('clsi-9') serverId.should.equal('clsi-9')
return done() return done()
@ -159,6 +165,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager.setServerId( return this.ClsiCookieManager.setServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.response, this.response,
null, null,
err => { err => {
@ -178,6 +185,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager.setServerId( return this.ClsiCookieManager.setServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.response, this.response,
null, null,
(err, serverId) => { (err, serverId) => {
@ -198,6 +206,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager.setServerId( return this.ClsiCookieManager.setServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.response, this.response,
null, null,
(err, serverId) => { (err, serverId) => {
@ -214,6 +223,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager.setServerId( return this.ClsiCookieManager.setServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.response, this.response,
null, null,
(err, serverId) => { (err, serverId) => {
@ -243,6 +253,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager.setServerId( return this.ClsiCookieManager.setServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.response, this.response,
null, null,
(err, serverId) => { (err, serverId) => {
@ -263,13 +274,14 @@ describe('ClsiCookieManager', function () {
beforeEach(function () { beforeEach(function () {
return (this.ClsiCookieManager._getServerId = sinon return (this.ClsiCookieManager._getServerId = sinon
.stub() .stub()
.callsArgWith(2, null, 'clsi-11')) .yields(null, 'clsi-11'))
}) })
it('should return a jar with the cookie set populated from redis', function (done) { it('should return a jar with the cookie set populated from redis', function (done) {
return this.ClsiCookieManager.getCookieJar( return this.ClsiCookieManager.getCookieJar(
this.project_id, this.project_id,
this.user_id, this.user_id,
'',
(err, jar) => { (err, jar) => {
jar._jar.store.idx['clsi.example.com']['/'][ jar._jar.store.idx['clsi.example.com']['/'][
this.settings.clsiCookie.key this.settings.clsiCookie.key
@ -293,6 +305,7 @@ describe('ClsiCookieManager', function () {
return this.ClsiCookieManager.getCookieJar( return this.ClsiCookieManager.getCookieJar(
this.project_id, this.project_id,
this.user_id, this.user_id,
'',
(err, jar) => { (err, jar) => {
assert.deepEqual(jar, realRequst.jar()) assert.deepEqual(jar, realRequst.jar())
return done() return done()

View file

@ -8,7 +8,7 @@ describe('ClsiManager', function () {
this.jar = { cookie: 'stuff' } this.jar = { cookie: 'stuff' }
this.ClsiCookieManager = { this.ClsiCookieManager = {
clearServerId: sinon.stub().yields(), clearServerId: sinon.stub().yields(),
getCookieJar: sinon.stub().callsArgWith(2, null, this.jar), getCookieJar: sinon.stub().yields(null, this.jar),
setServerId: sinon.stub().yields(null), setServerId: sinon.stub().yields(null),
_getServerId: sinon.stub(), _getServerId: sinon.stub(),
} }
@ -491,9 +491,10 @@ describe('ClsiManager', function () {
.calledWith( .calledWith(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
{ {
method: 'DELETE', method: 'DELETE',
url: `${this.settings.apis.clsi.url}/project/${this.project_id}/user/${this.user_id}`, url: `${this.settings.apis.clsi.url}/project/${this.project_id}/user/${this.user_id}?compileGroup=standard`,
}, },
'node-1' 'node-1'
) )
@ -922,12 +923,7 @@ describe('ClsiManager', function () {
beforeEach(function () { beforeEach(function () {
this.ClsiManager._makeRequest = sinon this.ClsiManager._makeRequest = sinon
.stub() .stub()
.callsArgWith( .yields(null, { statusCode: 204 }, (this.body = { mock: 'foo' }))
3,
null,
{ statusCode: 204 },
(this.body = { mock: 'foo' })
)
this.ClsiManager._postToClsi( this.ClsiManager._postToClsi(
this.project_id, this.project_id,
this.user_id, this.user_id,
@ -938,9 +934,9 @@ describe('ClsiManager', function () {
}) })
it('should send the request to the CLSI', function () { it('should send the request to the CLSI', function () {
const url = `${this.settings.apis.clsi.url}/project/${this.project_id}/user/${this.user_id}/compile` const url = `${this.settings.apis.clsi.url}/project/${this.project_id}/user/${this.user_id}/compile?compileGroup=standard`
this.ClsiManager._makeRequest this.ClsiManager._makeRequest
.calledWith(this.project_id, this.user_id, { .calledWith(this.project_id, this.user_id, 'standard', {
method: 'POST', method: 'POST',
url, url,
json: this.req, json: this.req,
@ -957,12 +953,7 @@ describe('ClsiManager', function () {
beforeEach(function () { beforeEach(function () {
this.ClsiManager._makeRequest = sinon this.ClsiManager._makeRequest = sinon
.stub() .stub()
.callsArgWith( .yields(null, { statusCode: 500 }, (this.body = { mock: 'foo' }))
3,
null,
{ statusCode: 500 },
(this.body = { mock: 'foo' })
)
this.ClsiManager._postToClsi( this.ClsiManager._postToClsi(
this.project_id, this.project_id,
this.user_id, this.user_id,
@ -983,8 +974,7 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequestWithClsiServerId = sinon this.ClsiManager._makeRequestWithClsiServerId = sinon
.stub() .stub()
.yields(null, { statusCode: 200 }, (this.body = { mock: 'foo' })) .yields(null, { statusCode: 200 }, (this.body = { mock: 'foo' }))
this.ClsiManager._buildRequest = sinon.stub().callsArgWith( this.ClsiManager._buildRequest = sinon.stub().yields(
2,
null, null,
(this.req = { (this.req = {
compile: { rootResourcePath: 'rootfile.text', options: {} }, compile: { rootResourcePath: 'rootfile.text', options: {} },
@ -998,7 +988,7 @@ describe('ClsiManager', function () {
this.project_id, this.project_id,
this.user_id, this.user_id,
false, false,
{}, { compileGroup: 'standard' },
'node-1', 'node-1',
this.callback this.callback
) )
@ -1009,9 +999,10 @@ describe('ClsiManager', function () {
.calledWith( .calledWith(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
{ {
method: 'GET', method: 'GET',
url: `http://clsi.example.com/project/${this.project_id}/user/${this.user_id}/wordcount`, url: `http://clsi.example.com/project/${this.project_id}/user/${this.user_id}/wordcount?compileGroup=standard`,
qs: { qs: {
file: 'rootfile.text', file: 'rootfile.text',
image: undefined, image: undefined,
@ -1034,7 +1025,7 @@ describe('ClsiManager', function () {
this.project_id, this.project_id,
this.user_id, this.user_id,
'main.tex', 'main.tex',
{}, { compileGroup: 'standard' },
'node-2', 'node-2',
this.callback this.callback
) )
@ -1045,9 +1036,10 @@ describe('ClsiManager', function () {
.calledWith( .calledWith(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
{ {
method: 'GET', method: 'GET',
url: `http://clsi.example.com/project/${this.project_id}/user/${this.user_id}/wordcount`, url: `http://clsi.example.com/project/${this.project_id}/user/${this.user_id}/wordcount?compileGroup=standard`,
qs: { file: 'main.tex', image: undefined }, qs: { file: 'main.tex', image: undefined },
json: true, json: true,
}, },
@ -1065,7 +1057,7 @@ describe('ClsiManager', function () {
this.project_id, this.project_id,
this.user_id, this.user_id,
'main.tex', 'main.tex',
{}, { compileGroup: 'standard' },
'node-3', 'node-3',
this.callback this.callback
) )
@ -1076,9 +1068,10 @@ describe('ClsiManager', function () {
.calledWith( .calledWith(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
{ {
method: 'GET', method: 'GET',
url: `http://clsi.example.com/project/${this.project_id}/user/${this.user_id}/wordcount`, url: `http://clsi.example.com/project/${this.project_id}/user/${this.user_id}/wordcount?compileGroup=standard`,
qs: { file: 'main.tex', image: this.image }, qs: { file: 'main.tex', image: this.image },
json: true, json: true,
}, },
@ -1103,6 +1096,7 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequest( this.ClsiManager._makeRequest(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
() => { () => {
const args = this.request.args[0] const args = this.request.args[0]
@ -1118,10 +1112,16 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequest( this.ClsiManager._makeRequest(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
() => { () => {
this.ClsiCookieManager.setServerId this.ClsiCookieManager.setServerId
.calledWith(this.project_id, this.user_id, this.response) .calledWith(
this.project_id,
this.user_id,
'standard',
this.response
)
.should.equal(true) .should.equal(true)
done() done()
} }
@ -1144,6 +1144,7 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequestWithClsiServerId( this.ClsiManager._makeRequestWithClsiServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
undefined, undefined,
err => { err => {
@ -1162,12 +1163,18 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequestWithClsiServerId( this.ClsiManager._makeRequestWithClsiServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
undefined, undefined,
err => { err => {
if (err) return done(err) if (err) return done(err)
this.ClsiCookieManager.setServerId this.ClsiCookieManager.setServerId
.calledWith(this.project_id, this.user_id, this.response) .calledWith(
this.project_id,
this.user_id,
'standard',
this.response
)
.should.equal(true) .should.equal(true)
done() done()
} }
@ -1180,6 +1187,7 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequestWithClsiServerId( this.ClsiManager._makeRequestWithClsiServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
'node-1', 'node-1',
err => { err => {
@ -1188,7 +1196,10 @@ describe('ClsiManager', function () {
expect(requestOpts.method).to.equal(this.opts.method) expect(requestOpts.method).to.equal(this.opts.method)
expect(requestOpts.url).to.equal(this.opts.url) expect(requestOpts.url).to.equal(this.opts.url)
expect(requestOpts.jar).to.not.exist expect(requestOpts.jar).to.not.exist
expect(requestOpts.qs).to.deep.equal({ clsiserverid: 'node-1' }) expect(requestOpts.qs).to.deep.equal({
clsiserverid: 'node-1',
compileGroup: 'standard',
})
done() done()
} }
) )
@ -1198,6 +1209,7 @@ describe('ClsiManager', function () {
this.ClsiManager._makeRequestWithClsiServerId( this.ClsiManager._makeRequestWithClsiServerId(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
'node-1', 'node-1',
err => { err => {
@ -1216,7 +1228,7 @@ describe('ClsiManager', function () {
this.response = { there: 'something' } this.response = { there: 'something' }
this.request.callsArgWith(1, null, this.response) this.request.callsArgWith(1, null, this.response)
this.opts = { this.opts = {
url: this.ClsiManager._getCompilerUrl(null, this.project_id), url: this.ClsiManager._getCompilerUrl('standard', this.project_id),
} }
}) })
@ -1224,11 +1236,12 @@ describe('ClsiManager', function () {
this.ClsiManager._makeNewBackendRequest( this.ClsiManager._makeNewBackendRequest(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
() => { () => {
const args = this.request.args[0] const args = this.request.args[0]
args[0].url.should.equal( args[0].url.should.equal(
`https://compiles.somewhere.test/project/${this.project_id}` `https://compiles.somewhere.test/project/${this.project_id}?compileGroup=standard`
) )
done() done()
} }
@ -1240,6 +1253,7 @@ describe('ClsiManager', function () {
this.ClsiManager._makeNewBackendRequest( this.ClsiManager._makeNewBackendRequest(
this.project_id, this.project_id,
this.user_id, this.user_id,
'standard',
this.opts, this.opts,
err => { err => {
expect(err).to.equal(undefined) expect(err).to.equal(undefined)

View file

@ -49,7 +49,7 @@ describe('CompileController', function () {
} }
this.jar = { cookie: 'stuff' } this.jar = { cookie: 'stuff' }
this.ClsiCookieManager = { this.ClsiCookieManager = {
getCookieJar: sinon.stub().callsArgWith(2, null, this.jar), getCookieJar: sinon.stub().yields(null, this.jar),
} }
this.SessionManager = { this.SessionManager = {
getLoggedInUser: sinon.stub().callsArgWith(1, null, this.user), getLoggedInUser: sinon.stub().callsArgWith(1, null, this.user),

View file

@ -58,6 +58,7 @@ describe('CompileManager', function () {
this.callback = sinon.stub() this.callback = sinon.stub()
return (this.limits = { return (this.limits = {
timeout: 42, timeout: 42,
compileGroup: 'standard',
}) })
}) })
@ -120,6 +121,7 @@ describe('CompileManager', function () {
return this.ClsiManager.sendRequest return this.ClsiManager.sendRequest
.calledWith(this.project_id, this.user_id, { .calledWith(this.project_id, this.user_id, {
timeout: this.limits.timeout, timeout: this.limits.timeout,
compileGroup: 'standard',
}) })
.should.equal(true) .should.equal(true)
}) })