mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #49 from sharelatex/ja-record-snapshots-of-ranges
Record a snapshot to mongo when a doc's comments/changes get collapsed
This commit is contained in:
commit
2a1e843558
11 changed files with 286 additions and 22 deletions
|
@ -1,13 +1,15 @@
|
|||
RangesTracker = require "./RangesTracker"
|
||||
logger = require "logger-sharelatex"
|
||||
_ = require "lodash"
|
||||
|
||||
module.exports = RangesManager =
|
||||
MAX_COMMENTS: 500
|
||||
MAX_CHANGES: 2000
|
||||
|
||||
applyUpdate: (project_id, doc_id, entries = {}, updates = [], newDocLines, callback = (error, new_entries) ->) ->
|
||||
{changes, comments} = entries
|
||||
applyUpdate: (project_id, doc_id, entries = {}, updates = [], newDocLines, callback = (error, new_entries, ranges_were_collapsed) ->) ->
|
||||
{changes, comments} = _.cloneDeep(entries)
|
||||
rangesTracker = new RangesTracker(changes, comments)
|
||||
emptyRangeCountBefore = RangesManager._emptyRangesCount(rangesTracker)
|
||||
for update in updates
|
||||
rangesTracker.track_changes = !!update.meta.tc
|
||||
if !!update.meta.tc
|
||||
|
@ -29,9 +31,11 @@ module.exports = RangesManager =
|
|||
logger.error {err: error, project_id, doc_id, newDocLines, updates}, "error validating ranges"
|
||||
return callback(error)
|
||||
|
||||
emptyRangeCountAfter = RangesManager._emptyRangesCount(rangesTracker)
|
||||
rangesWereCollapsed = emptyRangeCountAfter > emptyRangeCountBefore
|
||||
response = RangesManager._getRanges rangesTracker
|
||||
logger.log {project_id, doc_id, changesCount: response.changes?.length, commentsCount: response.comments?.length}, "applied updates to ranges"
|
||||
callback null, response
|
||||
logger.log {project_id, doc_id, changesCount: response.changes?.length, commentsCount: response.comments?.length, rangesWereCollapsed}, "applied updates to ranges"
|
||||
callback null, response, rangesWereCollapsed
|
||||
|
||||
acceptChanges: (change_ids, ranges, callback = (error, ranges) ->) ->
|
||||
{changes, comments} = ranges
|
||||
|
@ -60,3 +64,13 @@ module.exports = RangesManager =
|
|||
response ?= {}
|
||||
response.comments = rangesTracker.comments
|
||||
return response
|
||||
|
||||
_emptyRangesCount: (ranges) ->
|
||||
count = 0
|
||||
for comment in (ranges.comments or [])
|
||||
if comment.op.c == ""
|
||||
count++
|
||||
for change in (ranges.changes or []) when change.op.i?
|
||||
if change.op.i == ""
|
||||
count++
|
||||
return count
|
|
@ -1,6 +1,5 @@
|
|||
Settings = require('settings-sharelatex')
|
||||
rclient = require("redis-sharelatex").createClient(Settings.redis.documentupdater)
|
||||
_ = require('underscore')
|
||||
logger = require('logger-sharelatex')
|
||||
metrics = require('./Metrics')
|
||||
Errors = require "./Errors"
|
||||
|
|
42
services/document-updater/app/coffee/SnapshotManager.coffee
Normal file
42
services/document-updater/app/coffee/SnapshotManager.coffee
Normal file
|
@ -0,0 +1,42 @@
|
|||
{db, ObjectId} = require "./mongojs"
|
||||
|
||||
module.exports = SnapshotManager =
|
||||
recordSnapshot: (project_id, doc_id, version, pathname, lines, ranges, callback) ->
|
||||
try
|
||||
project_id = ObjectId(project_id)
|
||||
doc_id = ObjectId(doc_id)
|
||||
catch error
|
||||
return callback(error)
|
||||
db.docSnapshots.insert {
|
||||
project_id, doc_id, version, lines, pathname,
|
||||
ranges: SnapshotManager.jsonRangesToMongo(ranges),
|
||||
ts: new Date()
|
||||
}, callback
|
||||
# Suggested indexes:
|
||||
# db.docSnapshots.createIndex({project_id:1, doc_id:1})
|
||||
# db.docSnapshots.createIndex({ts:1},{expiresAfterSeconds: 30*24*3600)) # expires after 30 days
|
||||
|
||||
jsonRangesToMongo: (ranges) ->
|
||||
return null if !ranges?
|
||||
|
||||
updateMetadata = (metadata) ->
|
||||
if metadata?.ts?
|
||||
metadata.ts = new Date(metadata.ts)
|
||||
if metadata?.user_id?
|
||||
metadata.user_id = SnapshotManager._safeObjectId(metadata.user_id)
|
||||
|
||||
for change in ranges.changes or []
|
||||
change.id = SnapshotManager._safeObjectId(change.id)
|
||||
updateMetadata(change.metadata)
|
||||
for comment in ranges.comments or []
|
||||
comment.id = SnapshotManager._safeObjectId(comment.id)
|
||||
if comment.op?.t?
|
||||
comment.op.t = SnapshotManager._safeObjectId(comment.op.t)
|
||||
updateMetadata(comment.metadata)
|
||||
return ranges
|
||||
|
||||
_safeObjectId: (data) ->
|
||||
try
|
||||
return ObjectId(data)
|
||||
catch error
|
||||
return data
|
|
@ -4,13 +4,14 @@ RealTimeRedisManager = require "./RealTimeRedisManager"
|
|||
ShareJsUpdateManager = require "./ShareJsUpdateManager"
|
||||
HistoryManager = require "./HistoryManager"
|
||||
Settings = require('settings-sharelatex')
|
||||
_ = require("underscore")
|
||||
_ = require("lodash")
|
||||
async = require("async")
|
||||
logger = require('logger-sharelatex')
|
||||
Metrics = require "./Metrics"
|
||||
Errors = require "./Errors"
|
||||
DocumentManager = require "./DocumentManager"
|
||||
RangesManager = require "./RangesManager"
|
||||
SnapshotManager = require "./SnapshotManager"
|
||||
Profiler = require "./Profiler"
|
||||
|
||||
module.exports = UpdateManager =
|
||||
|
@ -76,10 +77,11 @@ module.exports = UpdateManager =
|
|||
return callback(error) if error?
|
||||
if !lines? or !version?
|
||||
return callback(new Errors.NotFoundError("document not found: #{doc_id}"))
|
||||
previousVersion = version
|
||||
ShareJsUpdateManager.applyUpdate project_id, doc_id, update, lines, version, (error, updatedDocLines, version, appliedOps) ->
|
||||
profile.log("sharejs.applyUpdate")
|
||||
return callback(error) if error?
|
||||
RangesManager.applyUpdate project_id, doc_id, ranges, appliedOps, updatedDocLines, (error, new_ranges) ->
|
||||
RangesManager.applyUpdate project_id, doc_id, ranges, appliedOps, updatedDocLines, (error, new_ranges, ranges_were_collapsed) ->
|
||||
UpdateManager._addProjectHistoryMetadataToOps(appliedOps, pathname, projectHistoryId, lines)
|
||||
profile.log("RangesManager.applyUpdate")
|
||||
return callback(error) if error?
|
||||
|
@ -88,7 +90,19 @@ module.exports = UpdateManager =
|
|||
return callback(error) if error?
|
||||
HistoryManager.recordAndFlushHistoryOps project_id, doc_id, appliedOps, doc_ops_length, project_ops_length, (error) ->
|
||||
profile.log("recordAndFlushHistoryOps")
|
||||
callback(error)
|
||||
return callback(error) if error?
|
||||
if ranges_were_collapsed
|
||||
logger.log {project_id, doc_id, previousVersion, lines, ranges, update}, "update collapsed some ranges, snapshotting previous content"
|
||||
# Do this last, since it's a mongo call, and so potentially longest running
|
||||
# If it overruns the lock, it's ok, since all of our redis work is done
|
||||
SnapshotManager.recordSnapshot project_id, doc_id, previousVersion, pathname, lines, ranges, (error) ->
|
||||
if error?
|
||||
logger.error {err: error, project_id, doc_id, version, lines, ranges}, "error recording snapshot"
|
||||
return callback(error)
|
||||
else
|
||||
callback()
|
||||
else
|
||||
callback()
|
||||
|
||||
lockUpdatesAndDo: (method, project_id, doc_id, args..., callback) ->
|
||||
profile = new Profiler("lockUpdatesAndDo", {project_id, doc_id})
|
||||
|
|
7
services/document-updater/app/coffee/mongojs.coffee
Normal file
7
services/document-updater/app/coffee/mongojs.coffee
Normal file
|
@ -0,0 +1,7 @@
|
|||
Settings = require "settings-sharelatex"
|
||||
mongojs = require "mongojs"
|
||||
db = mongojs(Settings.mongo.url, ["docSnapshots"])
|
||||
module.exports =
|
||||
db: db
|
||||
ObjectId: mongojs.ObjectId
|
||||
|
86
services/document-updater/npm-shrinkwrap.json
generated
86
services/document-updater/npm-shrinkwrap.json
generated
|
@ -291,6 +291,11 @@
|
|||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"bson": {
|
||||
"version": "1.0.9",
|
||||
"from": "bson@~1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz"
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.1",
|
||||
"from": "buffer-crc32@0.2.1",
|
||||
|
@ -301,6 +306,11 @@
|
|||
"from": "buffer-equal-constant-time@1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz"
|
||||
},
|
||||
"buffer-shims": {
|
||||
"version": "1.0.0",
|
||||
"from": "buffer-shims@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz"
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "3.0.0",
|
||||
"from": "builtin-modules@>=3.0.0 <4.0.0",
|
||||
|
@ -364,7 +374,7 @@
|
|||
},
|
||||
"coffee-script": {
|
||||
"version": "1.7.1",
|
||||
"from": "coffee-script@>=1.7.0 <1.8.0",
|
||||
"from": "coffee-script@1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz"
|
||||
},
|
||||
"combined-stream": {
|
||||
|
@ -491,6 +501,11 @@
|
|||
"from": "duplexify@>=3.6.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz"
|
||||
},
|
||||
"each-series": {
|
||||
"version": "1.0.0",
|
||||
"from": "each-series@^1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/each-series/-/each-series-1.0.0.tgz"
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"from": "ecc-jsbn@>=0.1.1 <0.2.0",
|
||||
|
@ -816,7 +831,7 @@
|
|||
},
|
||||
"lodash": {
|
||||
"version": "4.17.4",
|
||||
"from": "lodash@>=4.14.0 <5.0.0",
|
||||
"from": "lodash@4.17.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz"
|
||||
},
|
||||
"lodash.defaults": {
|
||||
|
@ -1093,6 +1108,43 @@
|
|||
"from": "module-details-from-path@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz"
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "2.2.36",
|
||||
"from": "mongodb@^2.2.31",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz",
|
||||
"dependencies": {
|
||||
"es6-promise": {
|
||||
"version": "3.2.1",
|
||||
"from": "es6-promise@3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz"
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"from": "process-nextick-args@>=1.0.6 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.2.7",
|
||||
"from": "readable-stream@2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz"
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"from": "string_decoder@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongodb-core": {
|
||||
"version": "2.1.20",
|
||||
"from": "mongodb-core@2.1.20",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz"
|
||||
},
|
||||
"mongojs": {
|
||||
"version": "2.6.0",
|
||||
"from": "mongojs@2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mongojs/-/mongojs-2.6.0.tgz"
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"from": "ms@2.0.0",
|
||||
|
@ -1158,6 +1210,11 @@
|
|||
"from": "parse-duration@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-0.1.1.tgz"
|
||||
},
|
||||
"parse-mongo-url": {
|
||||
"version": "1.1.1",
|
||||
"from": "parse-mongo-url@^1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz"
|
||||
},
|
||||
"parse-ms": {
|
||||
"version": "2.0.0",
|
||||
"from": "parse-ms@>=2.0.0 <3.0.0",
|
||||
|
@ -1405,6 +1462,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"require_optional": {
|
||||
"version": "1.0.1",
|
||||
"from": "require_optional@~1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz"
|
||||
},
|
||||
"require-in-the-middle": {
|
||||
"version": "3.1.0",
|
||||
"from": "require-in-the-middle@>=3.0.0 <4.0.0",
|
||||
|
@ -1420,6 +1482,11 @@
|
|||
"from": "resolve@>=1.5.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz"
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "2.0.0",
|
||||
"from": "resolve-from@^2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz"
|
||||
},
|
||||
"retry-axios": {
|
||||
"version": "0.3.2",
|
||||
"from": "retry-axios@>=0.3.2 <0.4.0",
|
||||
|
@ -1585,12 +1652,22 @@
|
|||
"from": "through2@>=2.0.3 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz"
|
||||
},
|
||||
"thunky": {
|
||||
"version": "1.0.3",
|
||||
"from": "thunky@^1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz"
|
||||
},
|
||||
"timekeeper": {
|
||||
"version": "2.0.0",
|
||||
"from": "timekeeper@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"to-mongodb-core": {
|
||||
"version": "2.0.0",
|
||||
"from": "to-mongodb-core@^2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.3",
|
||||
"from": "tough-cookie@>=2.3.3 <2.4.0",
|
||||
|
@ -1612,11 +1689,6 @@
|
|||
"from": "uid2@0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.2.tgz"
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.2.2",
|
||||
"from": "underscore@1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.2.2.tgz"
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"from": "uri-js@>=4.2.2 <5.0.0",
|
||||
|
|
|
@ -23,16 +23,17 @@
|
|||
"async": "^2.5.0",
|
||||
"coffee-script": "~1.7.0",
|
||||
"express": "3.3.4",
|
||||
"lodash": "^4.17.4",
|
||||
"logger-sharelatex": "^1.6.0",
|
||||
"lynx": "0.0.11",
|
||||
"metrics-sharelatex": "^2.1.1",
|
||||
"mongojs": "^2.6.0",
|
||||
"redis-sharelatex": "^1.0.5",
|
||||
"request": "2.25.0",
|
||||
"requestretry": "^1.12.0",
|
||||
"sandboxed-module": "~0.2.0",
|
||||
"settings-sharelatex": "^1.1.0",
|
||||
"sinon": "~1.5.2",
|
||||
"underscore": "1.2.2"
|
||||
"sinon": "~1.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bunyan": "~0.22.1",
|
||||
|
|
|
@ -4,11 +4,15 @@ chai.should()
|
|||
expect = chai.expect
|
||||
async = require "async"
|
||||
|
||||
{db, ObjectId} = require "../../../app/js/mongojs"
|
||||
MockWebApi = require "./helpers/MockWebApi"
|
||||
DocUpdaterClient = require "./helpers/DocUpdaterClient"
|
||||
DocUpdaterApp = require "./helpers/DocUpdaterApp"
|
||||
|
||||
describe "Ranges", ->
|
||||
before (done) ->
|
||||
DocUpdaterApp.ensureRunning done
|
||||
|
||||
describe "tracking changes from ops", ->
|
||||
before (done) ->
|
||||
@project_id = DocUpdaterClient.randomId()
|
||||
|
@ -306,3 +310,63 @@ describe "Ranges", ->
|
|||
ranges = data.ranges
|
||||
expect(ranges.changes).to.be.undefined
|
||||
done()
|
||||
|
||||
describe "deleting text surrounding a comment", ->
|
||||
before (done) ->
|
||||
@project_id = DocUpdaterClient.randomId()
|
||||
@user_id = DocUpdaterClient.randomId()
|
||||
@doc_id = DocUpdaterClient.randomId()
|
||||
MockWebApi.insertDoc @project_id, @doc_id, {
|
||||
lines: ["foo bar baz"]
|
||||
version: 0
|
||||
ranges: {
|
||||
comments: [{
|
||||
op: { c: "a", p: 5, tid: @tid = DocUpdaterClient.randomId() }
|
||||
metadata:
|
||||
user_id: @user_id
|
||||
ts: new Date()
|
||||
}]
|
||||
}
|
||||
}
|
||||
@updates = [{
|
||||
doc: @doc_id
|
||||
op: [{ d: "foo ", p: 0 }]
|
||||
v: 0
|
||||
meta: { user_id: @user_id }
|
||||
}, {
|
||||
doc: @doc_id
|
||||
op: [{ d: "bar ", p: 0 }]
|
||||
v: 1
|
||||
meta: { user_id: @user_id }
|
||||
}]
|
||||
jobs = []
|
||||
for update in @updates
|
||||
do (update) =>
|
||||
jobs.push (callback) => DocUpdaterClient.sendUpdate @project_id, @doc_id, update, callback
|
||||
DocUpdaterClient.preloadDoc @project_id, @doc_id, (error) =>
|
||||
throw error if error?
|
||||
async.series jobs, (error) ->
|
||||
throw error if error?
|
||||
setTimeout () =>
|
||||
DocUpdaterClient.getDoc @project_id, @doc_id, (error, res, data) =>
|
||||
throw error if error?
|
||||
done()
|
||||
, 200
|
||||
|
||||
it "should write a snapshot from before the destructive change", (done) ->
|
||||
DocUpdaterClient.getDoc @project_id, @doc_id, (error, res, data) =>
|
||||
return done(error) if error?
|
||||
db.docSnapshots.find {
|
||||
project_id: ObjectId(@project_id),
|
||||
doc_id: ObjectId(@doc_id)
|
||||
}, (error, docSnapshots) =>
|
||||
return done(error) if error?
|
||||
expect(docSnapshots.length).to.equal 1
|
||||
expect(docSnapshots[0].version).to.equal 1
|
||||
expect(docSnapshots[0].lines).to.deep.equal ["bar baz"]
|
||||
expect(docSnapshots[0].ranges.comments[0].op).to.deep.equal {
|
||||
c: "a",
|
||||
p: 1,
|
||||
tid: @tid
|
||||
}
|
||||
done()
|
||||
|
|
|
@ -3,7 +3,7 @@ chai = require('chai')
|
|||
should = chai.should()
|
||||
modulePath = "../../../../app/js/ProjectManager.js"
|
||||
SandboxedModule = require('sandboxed-module')
|
||||
_ = require('underscore')
|
||||
_ = require('lodash')
|
||||
|
||||
describe "ProjectManager", ->
|
||||
beforeEach ->
|
||||
|
|
|
@ -50,8 +50,9 @@ describe "RangesManager", ->
|
|||
|
||||
it "should return the modified the comments and changes", ->
|
||||
@callback.called.should.equal true
|
||||
[error, entries] = @callback.args[0]
|
||||
[error, entries, ranges_were_collapsed] = @callback.args[0]
|
||||
expect(error).to.be.null
|
||||
expect(ranges_were_collapsed).to.equal false
|
||||
entries.comments[0].op.should.deep.equal {
|
||||
c: "three "
|
||||
p: 8
|
||||
|
@ -180,6 +181,36 @@ describe "RangesManager", ->
|
|||
expect(error).to.not.be.null
|
||||
expect(error.message).to.equal("Change ({\"op\":{\"i\":\"five\",\"p\":15},\"metadata\":{\"user_id\":\"user-id-123\"}}) doesn't match text (\"our \")")
|
||||
|
||||
|
||||
describe "with an update that collapses a range", ->
|
||||
beforeEach ->
|
||||
@updates = [{
|
||||
meta:
|
||||
user_id: @user_id
|
||||
op: [{
|
||||
d: "one"
|
||||
p: 0
|
||||
t: "thread-id-1"
|
||||
}]
|
||||
}]
|
||||
@entries = {
|
||||
comments: [{
|
||||
op:
|
||||
c: "n"
|
||||
p: 1
|
||||
t: "thread-id-2"
|
||||
metadata:
|
||||
user_id: @user_id
|
||||
}]
|
||||
changes: []
|
||||
}
|
||||
@RangesManager.applyUpdate @project_id, @doc_id, @entries, @updates, @newDocLines, @callback
|
||||
|
||||
it "should return ranges_were_collapsed == true", ->
|
||||
@callback.called.should.equal true
|
||||
[error, entries, ranges_were_collapsed] = @callback.args[0]
|
||||
expect(ranges_were_collapsed).to.equal true
|
||||
|
||||
describe "acceptChanges", ->
|
||||
beforeEach ->
|
||||
@RangesManager = SandboxedModule.require modulePath,
|
||||
|
|
|
@ -23,6 +23,7 @@ describe "UpdateManager", ->
|
|||
"settings-sharelatex": @Settings = {}
|
||||
"./DocumentManager": @DocumentManager = {}
|
||||
"./RangesManager": @RangesManager = {}
|
||||
"./SnapshotManager": @SnapshotManager = {}
|
||||
"./Profiler": class Profiler
|
||||
log: sinon.stub().returns { end: sinon.stub() }
|
||||
end: sinon.stub()
|
||||
|
@ -169,7 +170,7 @@ describe "UpdateManager", ->
|
|||
@project_ops_length = sinon.stub()
|
||||
@pathname = '/a/b/c.tex'
|
||||
@DocumentManager.getDoc = sinon.stub().yields(null, @lines, @version, @ranges, @pathname, @projectHistoryId)
|
||||
@RangesManager.applyUpdate = sinon.stub().yields(null, @updated_ranges)
|
||||
@RangesManager.applyUpdate = sinon.stub().yields(null, @updated_ranges, false)
|
||||
@ShareJsUpdateManager.applyUpdate = sinon.stub().yields(null, @updatedDocLines, @version, @appliedOps)
|
||||
@RedisManager.updateDocument = sinon.stub().yields(null, @doc_ops_length, @project_ops_length)
|
||||
@RealTimeRedisManager.sendData = sinon.stub()
|
||||
|
@ -239,6 +240,25 @@ describe "UpdateManager", ->
|
|||
it "should call the callback with the error", ->
|
||||
@callback.calledWith(@error).should.equal true
|
||||
|
||||
describe "when ranges get collapsed", ->
|
||||
beforeEach ->
|
||||
@RangesManager.applyUpdate = sinon.stub().yields(null, @updated_ranges, true)
|
||||
@SnapshotManager.recordSnapshot = sinon.stub().yields()
|
||||
@UpdateManager.applyUpdate @project_id, @doc_id, @update, @callback
|
||||
|
||||
it "should call SnapshotManager.recordSnapshot", ->
|
||||
@SnapshotManager.recordSnapshot
|
||||
.calledWith(
|
||||
@project_id,
|
||||
@doc_id,
|
||||
@version,
|
||||
@pathname,
|
||||
@lines,
|
||||
@ranges
|
||||
)
|
||||
.should.equal true
|
||||
|
||||
|
||||
describe "_addProjectHistoryMetadataToOps", ->
|
||||
it "should add projectHistoryId, pathname and doc_length metadata to the ops", ->
|
||||
lines = [
|
||||
|
|
Loading…
Reference in a new issue