overleaf/services/document-updater/test/acceptance/js/helpers/DocUpdaterClient.js

213 lines
5.5 KiB
JavaScript
Raw Normal View History

let DocUpdaterClient
const Settings = require('@overleaf/settings')
2021-02-02 10:10:04 -05:00
const _ = require('lodash')
const rclient = require('@overleaf/redis-wrapper').createClient(
Settings.redis.documentupdater
)
const keys = Settings.redis.documentupdater.key_schema
const request = require('request').defaults({ jar: false })
const async = require('async')
const rclientSub = require('@overleaf/redis-wrapper').createClient(
Settings.redis.pubsub
)
2020-05-20 16:12:27 -04:00
rclientSub.subscribe('applied-ops')
rclientSub.setMaxListeners(0)
module.exports = DocUpdaterClient = {
randomId() {
2020-05-20 16:06:42 -04:00
let str = ''
for (let i = 0; i < 24; i++) {
str += Math.floor(Math.random() * 16).toString(16)
}
return str
},
subscribeToAppliedOps(callback) {
2020-05-20 16:12:27 -04:00
rclientSub.on('message', callback)
},
2021-02-02 10:10:04 -05:00
_getPendingUpdateListKey() {
const shard = _.random(0, Settings.dispatcherCount - 1)
2021-02-02 10:10:04 -05:00
if (shard === 0) {
return 'pending-updates-list'
} else {
return `pending-updates-list-${shard}`
}
},
2020-05-20 16:12:27 -04:00
sendUpdate(projectId, docId, update, callback) {
2020-05-20 15:54:36 -04:00
rclient.rpush(
2020-05-20 16:12:27 -04:00
keys.pendingUpdates({ doc_id: docId }),
JSON.stringify(update),
(error) => {
2020-05-20 15:53:06 -04:00
if (error) {
return callback(error)
}
2020-05-20 16:12:27 -04:00
const docKey = `${projectId}:${docId}`
rclient.sadd('DocsWithPendingUpdates', docKey, (error) => {
2020-05-20 15:53:06 -04:00
if (error) {
return callback(error)
}
2021-02-02 10:10:04 -05:00
rclient.rpush(
DocUpdaterClient._getPendingUpdateListKey(),
docKey,
callback
)
})
}
)
},
2020-05-20 16:12:27 -04:00
sendUpdates(projectId, docId, updates, callback) {
DocUpdaterClient.preloadDoc(projectId, docId, (error) => {
2020-05-20 15:53:06 -04:00
if (error) {
return callback(error)
}
2020-05-20 16:06:42 -04:00
const jobs = updates.map((update) => (callback) => {
2020-05-20 16:12:27 -04:00
DocUpdaterClient.sendUpdate(projectId, docId, update, callback)
2020-05-20 16:06:42 -04:00
})
2020-05-20 16:08:03 -04:00
async.series(jobs, (err) => {
if (err) {
return callback(err)
}
2020-05-20 16:12:27 -04:00
DocUpdaterClient.waitForPendingUpdates(projectId, docId, callback)
2020-05-20 16:08:03 -04:00
})
})
},
2020-05-20 16:12:27 -04:00
waitForPendingUpdates(projectId, docId, callback) {
2020-05-20 15:54:36 -04:00
async.retry(
{ times: 30, interval: 100 },
(cb) =>
2020-05-20 16:12:27 -04:00
rclient.llen(keys.pendingUpdates({ doc_id: docId }), (err, length) => {
2020-05-20 16:08:03 -04:00
if (err) {
return cb(err)
}
if (length > 0) {
2020-05-20 15:54:36 -04:00
cb(new Error('updates still pending'))
} else {
2020-05-20 15:54:36 -04:00
cb()
}
}),
callback
)
},
2020-05-20 16:12:27 -04:00
getDoc(projectId, docId, callback) {
2020-05-20 15:54:36 -04:00
request.get(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc/${docId}`,
(error, res, body) => {
if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
body = JSON.parse(body)
}
2020-05-20 15:54:36 -04:00
callback(error, res, body)
}
)
},
2020-05-20 16:12:27 -04:00
getDocAndRecentOps(projectId, docId, fromVersion, callback) {
2020-05-20 15:54:36 -04:00
request.get(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc/${docId}?fromVersion=${fromVersion}`,
(error, res, body) => {
if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
body = JSON.parse(body)
}
2020-05-20 15:54:36 -04:00
callback(error, res, body)
}
)
},
2020-05-20 16:12:27 -04:00
preloadDoc(projectId, docId, callback) {
DocUpdaterClient.getDoc(projectId, docId, callback)
},
2020-05-20 16:12:27 -04:00
flushDoc(projectId, docId, callback) {
2020-05-20 15:54:36 -04:00
request.post(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc/${docId}/flush`,
(error, res, body) => callback(error, res, body)
)
},
2020-05-20 16:12:27 -04:00
setDocLines(projectId, docId, lines, source, userId, undoing, callback) {
2020-05-20 15:54:36 -04:00
request.post(
{
2020-05-20 16:12:27 -04:00
url: `http://localhost:3003/project/${projectId}/doc/${docId}`,
json: {
lines,
source,
2020-05-20 16:12:27 -04:00
user_id: userId,
undoing
}
},
(error, res, body) => callback(error, res, body)
)
},
2020-05-20 16:12:27 -04:00
deleteDoc(projectId, docId, callback) {
2020-05-20 15:54:36 -04:00
request.del(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc/${docId}`,
(error, res, body) => callback(error, res, body)
)
},
2020-05-20 16:12:27 -04:00
flushProject(projectId, callback) {
request.post(`http://localhost:3003/project/${projectId}/flush`, callback)
},
2020-05-20 16:12:27 -04:00
deleteProject(projectId, callback) {
request.del(`http://localhost:3003/project/${projectId}`, callback)
},
2020-05-20 16:12:27 -04:00
deleteProjectOnShutdown(projectId, callback) {
2020-05-20 15:54:36 -04:00
request.del(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}?background=true&shutdown=true`,
callback
)
},
flushOldProjects(callback) {
2020-05-20 15:54:36 -04:00
request.get(
'http://localhost:3003/flush_queued_projects?min_delete_age=1',
callback
)
},
2020-05-20 16:12:27 -04:00
acceptChange(projectId, docId, changeId, callback) {
2020-05-20 15:54:36 -04:00
request.post(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc/${docId}/change/${changeId}/accept`,
callback
)
},
2020-05-20 16:12:27 -04:00
removeComment(projectId, docId, comment, callback) {
2020-05-20 15:54:36 -04:00
request.del(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc/${docId}/comment/${comment}`,
callback
)
},
2020-05-20 16:12:27 -04:00
getProjectDocs(projectId, projectStateHash, callback) {
2020-05-20 15:54:36 -04:00
request.get(
2020-05-20 16:12:27 -04:00
`http://localhost:3003/project/${projectId}/doc?state=${projectStateHash}`,
(error, res, body) => {
if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
body = JSON.parse(body)
}
2020-05-20 15:54:36 -04:00
callback(error, res, body)
}
)
},
sendProjectUpdate(projectId, userId, updates, version, callback) {
2020-05-20 15:54:36 -04:00
request.post(
{
2020-05-20 16:12:27 -04:00
url: `http://localhost:3003/project/${projectId}`,
json: { userId, updates, version }
},
(error, res, body) => callback(error, res, body)
)
}
}