|
|
@@ -1,7 +1,6 @@
|
|
|
-import async from 'async'
|
|
|
import nock from 'nock'
|
|
|
import { expect } from 'chai'
|
|
|
-import request from 'request'
|
|
|
+import { fetchNothing, fetchJsonWithResponse } from '@overleaf/fetch-utils'
|
|
|
import assert from 'node:assert'
|
|
|
import mongodb from 'mongodb-legacy'
|
|
|
import * as ProjectHistoryClient from './helpers/ProjectHistoryClient.js'
|
|
|
@@ -15,42 +14,38 @@ const MockWeb = () => nock('http://127.0.0.1:3000')
|
|
|
describe('Flushing old queues', function () {
|
|
|
const historyId = new ObjectId().toString()
|
|
|
|
|
|
- beforeEach(function (done) {
|
|
|
+ beforeEach(async function () {
|
|
|
this.timestamp = new Date()
|
|
|
|
|
|
- ProjectHistoryApp.ensureRunning(error => {
|
|
|
- if (error) {
|
|
|
- throw error
|
|
|
- }
|
|
|
- this.projectId = new ObjectId().toString()
|
|
|
- this.docId = new ObjectId().toString()
|
|
|
- this.fileId = new ObjectId().toString()
|
|
|
+ await ProjectHistoryApp.promises.ensureRunning()
|
|
|
+ this.projectId = new ObjectId().toString()
|
|
|
+ this.docId = new ObjectId().toString()
|
|
|
+ this.fileId = new ObjectId().toString()
|
|
|
|
|
|
- MockHistoryStore().post('/api/projects').reply(200, {
|
|
|
- projectId: historyId,
|
|
|
- })
|
|
|
- MockWeb()
|
|
|
- .get(`/project/${this.projectId}/details`)
|
|
|
- .reply(200, {
|
|
|
- name: 'Test Project',
|
|
|
- overleaf: {
|
|
|
- history: {
|
|
|
- id: historyId,
|
|
|
- },
|
|
|
+ MockHistoryStore().post('/api/projects').reply(200, {
|
|
|
+ projectId: historyId,
|
|
|
+ })
|
|
|
+ MockWeb()
|
|
|
+ .get(`/project/${this.projectId}/details`)
|
|
|
+ .reply(200, {
|
|
|
+ name: 'Test Project',
|
|
|
+ overleaf: {
|
|
|
+ history: {
|
|
|
+ id: historyId,
|
|
|
},
|
|
|
- })
|
|
|
- MockHistoryStore()
|
|
|
- .get(`/api/projects/${historyId}/latest/history`)
|
|
|
- .reply(200, {
|
|
|
- chunk: {
|
|
|
- startVersion: 0,
|
|
|
- history: {
|
|
|
- changes: [],
|
|
|
- },
|
|
|
+ },
|
|
|
+ })
|
|
|
+ MockHistoryStore()
|
|
|
+ .get(`/api/projects/${historyId}/latest/history`)
|
|
|
+ .reply(200, {
|
|
|
+ chunk: {
|
|
|
+ startVersion: 0,
|
|
|
+ history: {
|
|
|
+ changes: [],
|
|
|
},
|
|
|
- })
|
|
|
- ProjectHistoryClient.initializeProject(historyId, done)
|
|
|
- })
|
|
|
+ },
|
|
|
+ })
|
|
|
+ await ProjectHistoryClient.promises.initializeProject(historyId)
|
|
|
})
|
|
|
|
|
|
afterEach(function () {
|
|
|
@@ -59,7 +54,7 @@ describe('Flushing old queues', function () {
|
|
|
|
|
|
describe('retrying an unflushed project', function () {
|
|
|
describe('when the update is older than the cutoff', function () {
|
|
|
- beforeEach(function (done) {
|
|
|
+ beforeEach(async function () {
|
|
|
this.flushCall = MockHistoryStore()
|
|
|
.put(
|
|
|
`/api/projects/${historyId}/blobs/0a207c060e61f3b88eaee0a8cd0696f46fb155eb`
|
|
|
@@ -73,69 +68,56 @@ describe('Flushing old queues', function () {
|
|
|
doc: this.docId,
|
|
|
meta: { user_id: this.user_id, ts: new Date() },
|
|
|
}
|
|
|
- async.series(
|
|
|
- [
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.pushRawUpdate(this.projectId, update, cb),
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.setFirstOpTimestamp(
|
|
|
- this.projectId,
|
|
|
- Date.now() - 24 * 3600 * 1000,
|
|
|
- cb
|
|
|
- ),
|
|
|
- ],
|
|
|
- done
|
|
|
+ await ProjectHistoryClient.promises.pushRawUpdate(
|
|
|
+ this.projectId,
|
|
|
+ update
|
|
|
+ )
|
|
|
+ await ProjectHistoryClient.promises.setFirstOpTimestamp(
|
|
|
+ this.projectId,
|
|
|
+ Date.now() - 24 * 3600 * 1000
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it('flushes the project history queue', function (done) {
|
|
|
- request.post(
|
|
|
+ it('flushes the project history queue', async function () {
|
|
|
+ const response = await fetchNothing(
|
|
|
+ 'http://127.0.0.1:3054/flush/old?maxAge=10800',
|
|
|
{
|
|
|
- url: 'http://127.0.0.1:3054/flush/old?maxAge=10800',
|
|
|
- },
|
|
|
- (error, res, body) => {
|
|
|
- if (error) {
|
|
|
- return done(error)
|
|
|
- }
|
|
|
- expect(res.statusCode).to.equal(200)
|
|
|
- assert(
|
|
|
- this.flushCall.isDone(),
|
|
|
- 'made calls to history service to store updates'
|
|
|
- )
|
|
|
- done()
|
|
|
+ method: 'POST',
|
|
|
}
|
|
|
)
|
|
|
+ expect(response.status).to.equal(200)
|
|
|
+ assert(
|
|
|
+ this.flushCall.isDone(),
|
|
|
+ 'made calls to history service to store updates'
|
|
|
+ )
|
|
|
})
|
|
|
|
|
|
- it('flushes the project history queue in the background when requested', function (done) {
|
|
|
- request.post(
|
|
|
+ it('flushes the project history queue in the background when requested', async function () {
|
|
|
+ const { json, response } = await fetchJsonWithResponse(
|
|
|
+ 'http://127.0.0.1:3054/flush/old?maxAge=10800&background=1',
|
|
|
{
|
|
|
- url: 'http://127.0.0.1:3054/flush/old?maxAge=10800&background=1',
|
|
|
- },
|
|
|
- (error, res, body) => {
|
|
|
- if (error) {
|
|
|
- return done(error)
|
|
|
- }
|
|
|
- expect(res.statusCode).to.equal(200)
|
|
|
- expect(body).to.equal('{"message":"running flush in background"}')
|
|
|
- assert(
|
|
|
- !this.flushCall.isDone(),
|
|
|
- 'did not make calls to history service to store updates in the foreground'
|
|
|
- )
|
|
|
- setTimeout(() => {
|
|
|
- assert(
|
|
|
- this.flushCall.isDone(),
|
|
|
- 'made calls to history service to store updates in the background'
|
|
|
- )
|
|
|
- done()
|
|
|
- }, 1_000)
|
|
|
+ method: 'POST',
|
|
|
}
|
|
|
)
|
|
|
+ expect(response.status).to.equal(200)
|
|
|
+ expect(json).to.deep.equal({
|
|
|
+ message: 'running flush in background',
|
|
|
+ })
|
|
|
+ assert(
|
|
|
+ !this.flushCall.isDone(),
|
|
|
+ 'did not make calls to history service to store updates in the foreground'
|
|
|
+ )
|
|
|
+
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
+ assert(
|
|
|
+ this.flushCall.isDone(),
|
|
|
+ 'made calls to history service to store updates in the background'
|
|
|
+ )
|
|
|
})
|
|
|
})
|
|
|
|
|
|
describe('when the update is newer than the cutoff', function () {
|
|
|
- beforeEach(function (done) {
|
|
|
+ beforeEach(async function () {
|
|
|
this.flushCall = MockHistoryStore()
|
|
|
.put(
|
|
|
`/api/projects/${historyId}/blobs/0a207c060e61f3b88eaee0a8cd0696f46fb155eb`
|
|
|
@@ -149,38 +131,28 @@ describe('Flushing old queues', function () {
|
|
|
doc: this.docId,
|
|
|
meta: { user_id: this.user_id, ts: new Date() },
|
|
|
}
|
|
|
- async.series(
|
|
|
- [
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.pushRawUpdate(this.projectId, update, cb),
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.setFirstOpTimestamp(
|
|
|
- this.projectId,
|
|
|
- Date.now() - 60 * 1000,
|
|
|
- cb
|
|
|
- ),
|
|
|
- ],
|
|
|
- done
|
|
|
+ await ProjectHistoryClient.promises.pushRawUpdate(
|
|
|
+ this.projectId,
|
|
|
+ update
|
|
|
+ )
|
|
|
+ await ProjectHistoryClient.promises.setFirstOpTimestamp(
|
|
|
+ this.projectId,
|
|
|
+ Date.now() - 60 * 1000
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it('does not flush the project history queue', function (done) {
|
|
|
- request.post(
|
|
|
+ it('does not flush the project history queue', async function () {
|
|
|
+ const response = await fetchNothing(
|
|
|
+ `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}`,
|
|
|
{
|
|
|
- url: `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}`,
|
|
|
- },
|
|
|
- (error, res, body) => {
|
|
|
- if (error) {
|
|
|
- return done(error)
|
|
|
- }
|
|
|
- expect(res.statusCode).to.equal(200)
|
|
|
- assert(
|
|
|
- !this.flushCall.isDone(),
|
|
|
- 'did not make calls to history service to store updates'
|
|
|
- )
|
|
|
- done()
|
|
|
+ method: 'POST',
|
|
|
}
|
|
|
)
|
|
|
+ expect(response.status).to.equal(200)
|
|
|
+ assert(
|
|
|
+ !this.flushCall.isDone(),
|
|
|
+ 'did not make calls to history service to store updates'
|
|
|
+ )
|
|
|
})
|
|
|
})
|
|
|
|
|
|
@@ -191,7 +163,7 @@ describe('Flushing old queues', function () {
|
|
|
afterEach(function () {
|
|
|
Settings.shortHistoryQueues.length = 0
|
|
|
})
|
|
|
- beforeEach(function (done) {
|
|
|
+ beforeEach(async function () {
|
|
|
this.flushCall = MockHistoryStore()
|
|
|
.put(
|
|
|
`/api/projects/${historyId}/blobs/0a207c060e61f3b88eaee0a8cd0696f46fb155eb`
|
|
|
@@ -205,69 +177,56 @@ describe('Flushing old queues', function () {
|
|
|
doc: this.docId,
|
|
|
meta: { user_id: this.user_id, ts: new Date() },
|
|
|
}
|
|
|
- async.series(
|
|
|
- [
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.pushRawUpdate(this.projectId, update, cb),
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.setFirstOpTimestamp(
|
|
|
- this.projectId,
|
|
|
- Date.now() - 60 * 1000,
|
|
|
- cb
|
|
|
- ),
|
|
|
- ],
|
|
|
- done
|
|
|
+ await ProjectHistoryClient.promises.pushRawUpdate(
|
|
|
+ this.projectId,
|
|
|
+ update
|
|
|
+ )
|
|
|
+ await ProjectHistoryClient.promises.setFirstOpTimestamp(
|
|
|
+ this.projectId,
|
|
|
+ Date.now() - 60 * 1000
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it('flushes the project history queue', function (done) {
|
|
|
- request.post(
|
|
|
+ it('flushes the project history queue', async function () {
|
|
|
+ const response = await fetchNothing(
|
|
|
+ `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}`,
|
|
|
{
|
|
|
- url: `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}`,
|
|
|
- },
|
|
|
- (error, res, body) => {
|
|
|
- if (error) {
|
|
|
- return done(error)
|
|
|
- }
|
|
|
- expect(res.statusCode).to.equal(200)
|
|
|
- assert(
|
|
|
- this.flushCall.isDone(),
|
|
|
- 'made calls to history service to store updates'
|
|
|
- )
|
|
|
- done()
|
|
|
+ method: 'POST',
|
|
|
}
|
|
|
)
|
|
|
+ expect(response.status).to.equal(200)
|
|
|
+ assert(
|
|
|
+ this.flushCall.isDone(),
|
|
|
+ 'made calls to history service to store updates'
|
|
|
+ )
|
|
|
})
|
|
|
|
|
|
- it('flushes the project history queue in the background when requested', function (done) {
|
|
|
- request.post(
|
|
|
+ it('flushes the project history queue in the background when requested', async function () {
|
|
|
+ const { json, response } = await fetchJsonWithResponse(
|
|
|
+ `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}&background=1`,
|
|
|
{
|
|
|
- url: `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}&background=1`,
|
|
|
- },
|
|
|
- (error, res, body) => {
|
|
|
- if (error) {
|
|
|
- return done(error)
|
|
|
- }
|
|
|
- expect(res.statusCode).to.equal(200)
|
|
|
- expect(body).to.equal('{"message":"running flush in background"}')
|
|
|
- assert(
|
|
|
- !this.flushCall.isDone(),
|
|
|
- 'did not make calls to history service to store updates in the foreground'
|
|
|
- )
|
|
|
- setTimeout(() => {
|
|
|
- assert(
|
|
|
- this.flushCall.isDone(),
|
|
|
- 'made calls to history service to store updates in the background'
|
|
|
- )
|
|
|
- done()
|
|
|
- }, 1_000)
|
|
|
+ method: 'POST',
|
|
|
}
|
|
|
)
|
|
|
+ expect(response.status).to.equal(200)
|
|
|
+ expect(json).to.deep.equal({
|
|
|
+ message: 'running flush in background',
|
|
|
+ })
|
|
|
+ assert(
|
|
|
+ !this.flushCall.isDone(),
|
|
|
+ 'did not make calls to history service to store updates in the foreground'
|
|
|
+ )
|
|
|
+
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
+ assert(
|
|
|
+ this.flushCall.isDone(),
|
|
|
+ 'made calls to history service to store updates in the background'
|
|
|
+ )
|
|
|
})
|
|
|
})
|
|
|
|
|
|
describe('when the update does not have a timestamp', function () {
|
|
|
- beforeEach(function (done) {
|
|
|
+ beforeEach(async function () {
|
|
|
this.flushCall = MockHistoryStore()
|
|
|
.put(
|
|
|
`/api/projects/${historyId}/blobs/0a207c060e61f3b88eaee0a8cd0696f46fb155eb`
|
|
|
@@ -282,43 +241,41 @@ describe('Flushing old queues', function () {
|
|
|
meta: { user_id: this.user_id, ts: new Date() },
|
|
|
}
|
|
|
this.startDate = Date.now()
|
|
|
- async.series(
|
|
|
- [
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.pushRawUpdate(this.projectId, update, cb),
|
|
|
- cb =>
|
|
|
- ProjectHistoryClient.clearFirstOpTimestamp(this.projectId, cb),
|
|
|
- ],
|
|
|
- done
|
|
|
+ await ProjectHistoryClient.promises.pushRawUpdate(
|
|
|
+ this.projectId,
|
|
|
+ update
|
|
|
)
|
|
|
+ await new Promise((resolve, reject) => {
|
|
|
+ ProjectHistoryClient.clearFirstOpTimestamp(this.projectId, err => {
|
|
|
+ if (err) reject(err)
|
|
|
+ else resolve()
|
|
|
+ })
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- it('flushes the project history queue anyway', function (done) {
|
|
|
- request.post(
|
|
|
+ it('flushes the project history queue anyway', async function () {
|
|
|
+ const response = await fetchNothing(
|
|
|
+ `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}`,
|
|
|
{
|
|
|
- url: `http://127.0.0.1:3054/flush/old?maxAge=${3 * 3600}`,
|
|
|
- },
|
|
|
- (error, res, body) => {
|
|
|
- if (error) {
|
|
|
- return done(error)
|
|
|
- }
|
|
|
- expect(res.statusCode).to.equal(200)
|
|
|
- assert(
|
|
|
- this.flushCall.isDone(),
|
|
|
- 'made calls to history service to store updates'
|
|
|
- )
|
|
|
- ProjectHistoryClient.getFirstOpTimestamp(
|
|
|
- this.projectId,
|
|
|
- (err, result) => {
|
|
|
- if (err) {
|
|
|
- return done(err)
|
|
|
- }
|
|
|
- expect(result).to.be.null
|
|
|
- done()
|
|
|
- }
|
|
|
- )
|
|
|
+ method: 'POST',
|
|
|
}
|
|
|
)
|
|
|
+ expect(response.status).to.equal(200)
|
|
|
+ assert(
|
|
|
+ this.flushCall.isDone(),
|
|
|
+ 'made calls to history service to store updates'
|
|
|
+ )
|
|
|
+
|
|
|
+ const result = await new Promise((resolve, reject) => {
|
|
|
+ ProjectHistoryClient.getFirstOpTimestamp(
|
|
|
+ this.projectId,
|
|
|
+ (err, result) => {
|
|
|
+ if (err) reject(err)
|
|
|
+ else resolve(result)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ })
|
|
|
+ expect(result).to.be.null
|
|
|
})
|
|
|
})
|
|
|
})
|