mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-28 00:11:26 +00:00
Generate deterministic range ids based on seed
This commit is contained in:
parent
2c7029cc50
commit
7cac2f7d76
3 changed files with 23 additions and 49 deletions
|
@ -8,6 +8,8 @@ module.exports = RangesManager =
|
|||
rangesTracker = new RangesTracker(changes, comments)
|
||||
for update in updates
|
||||
rangesTracker.track_changes = !!update.meta.tc
|
||||
if !!update.meta.tc
|
||||
rangesTracker.setIdSeed(update.meta.tc)
|
||||
for op in update.op
|
||||
rangesTracker.applyOp(op, { user_id: update.meta?.user_id })
|
||||
|
||||
|
|
|
@ -35,18 +35,19 @@ load = (EventEmitter) ->
|
|||
# * Inserts by another user will not combine with inserts by the first user. If they are in the
|
||||
# middle of a previous insert by the first user, the original insert will be split into two.
|
||||
constructor: (@changes = [], @comments = []) ->
|
||||
# Change objects have the following structure:
|
||||
# {
|
||||
# id: ... # Uniquely generated by us
|
||||
# op: { # ShareJs style op tracking the offset (p) and content inserted (i) or deleted (d)
|
||||
# i: "..."
|
||||
# p: 42
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# Ids are used to uniquely identify a change, e.g. for updating it in the database, or keeping in
|
||||
# sync with Ace ranges.
|
||||
@id = 0
|
||||
|
||||
getIdSeed: () ->
|
||||
return @id_seed
|
||||
|
||||
setIdSeed: (seed) ->
|
||||
@id_seed = seed
|
||||
@id_increment = 0
|
||||
|
||||
newId: () ->
|
||||
@id_increment++
|
||||
increment = @id_increment.toString(16)
|
||||
id = @id_seed + '000000'.substr(0, 6 - increment.length) + increment;
|
||||
return id
|
||||
|
||||
getComment: (comment_id) ->
|
||||
comment = null
|
||||
|
@ -56,19 +57,6 @@ load = (EventEmitter) ->
|
|||
break
|
||||
return comment
|
||||
|
||||
resolveCommentId: (comment_id, resolved_data) ->
|
||||
comment = @getComment(comment_id)
|
||||
return if !comment?
|
||||
comment.metadata.resolved = true
|
||||
comment.metadata.resolved_data = resolved_data
|
||||
@emit "comment:resolved", comment
|
||||
|
||||
unresolveCommentId: (comment_id) ->
|
||||
comment = @getComment(comment_id)
|
||||
return if !comment?
|
||||
comment.metadata.resolved = false
|
||||
@emit "comment:unresolved", comment
|
||||
|
||||
removeCommentId: (comment_id) ->
|
||||
comment = @getComment(comment_id)
|
||||
return if !comment?
|
||||
|
@ -88,7 +76,7 @@ load = (EventEmitter) ->
|
|||
return if !change?
|
||||
@_removeChange(change)
|
||||
|
||||
applyOp: (op, metadata) ->
|
||||
applyOp: (op, metadata = {}) ->
|
||||
metadata.ts ?= new Date()
|
||||
# Apply an op that has been applied to the document to our changes to keep them up to date
|
||||
if op.i?
|
||||
|
@ -105,7 +93,7 @@ load = (EventEmitter) ->
|
|||
addComment: (op, metadata) ->
|
||||
# TODO: Don't allow overlapping comments?
|
||||
@comments.push comment = {
|
||||
id: @_newId()
|
||||
id: @newId()
|
||||
op: # Copy because we'll modify in place
|
||||
c: op.c
|
||||
p: op.p
|
||||
|
@ -394,28 +382,9 @@ load = (EventEmitter) ->
|
|||
if moved_changes.length > 0
|
||||
@emit "changes:moved", moved_changes
|
||||
|
||||
_newId: () ->
|
||||
# Generate a Mongo ObjectId
|
||||
# Reference: https://github.com/dreampulse/ObjectId.js/blob/master/src/main/javascript/Objectid.js
|
||||
@_pid ?= Math.floor(Math.random() * (32767))
|
||||
@_machine ?= Math.floor(Math.random() * (16777216))
|
||||
timestamp = Math.floor(new Date().valueOf() / 1000)
|
||||
@_increment ?= 0
|
||||
@_increment++
|
||||
|
||||
timestamp = timestamp.toString(16)
|
||||
machine = @_machine.toString(16)
|
||||
pid = @_pid.toString(16)
|
||||
increment = @_increment.toString(16)
|
||||
|
||||
return '00000000'.substr(0, 8 - timestamp.length) + timestamp +
|
||||
'000000'.substr(0, 6 - machine.length) + machine +
|
||||
'0000'.substr(0, 4 - pid.length) + pid +
|
||||
'000000'.substr(0, 6 - increment.length) + increment;
|
||||
|
||||
_addOp: (op, metadata) ->
|
||||
change = {
|
||||
id: @_newId()
|
||||
id: @newId()
|
||||
op: op
|
||||
metadata: metadata
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ describe "Ranges", ->
|
|||
before (done) ->
|
||||
@project_id = DocUpdaterClient.randomId()
|
||||
@user_id = DocUpdaterClient.randomId()
|
||||
@id_seed = "587357bd35e64f6157"
|
||||
@doc = {
|
||||
id: DocUpdaterClient.randomId()
|
||||
lines: ["aaa"]
|
||||
|
@ -25,7 +26,7 @@ describe "Ranges", ->
|
|||
doc: @doc.id
|
||||
op: [{ i: "456", p: 5 }]
|
||||
v: 1
|
||||
meta: { user_id: @user_id, tc: 1 }
|
||||
meta: { user_id: @user_id, tc: @id_seed }
|
||||
}, {
|
||||
doc: @doc.id
|
||||
op: [{ d: "12", p: 1 }]
|
||||
|
@ -52,6 +53,7 @@ describe "Ranges", ->
|
|||
ranges = data.ranges
|
||||
change = ranges.changes[0]
|
||||
change.op.should.deep.equal { i: "456", p: 3 }
|
||||
change.id.should.equal @id_seed + "000001"
|
||||
change.metadata.user_id.should.equal @user_id
|
||||
done()
|
||||
|
||||
|
@ -135,6 +137,7 @@ describe "Ranges", ->
|
|||
before (done) ->
|
||||
@project_id = DocUpdaterClient.randomId()
|
||||
@user_id = DocUpdaterClient.randomId()
|
||||
@id_seed = "587357bd35e64f6157"
|
||||
@doc = {
|
||||
id: DocUpdaterClient.randomId()
|
||||
lines: ["a123aa"]
|
||||
|
@ -143,7 +146,7 @@ describe "Ranges", ->
|
|||
doc: @doc.id
|
||||
op: [{ i: "456", p: 5 }]
|
||||
v: 0
|
||||
meta: { user_id: @user_id, tc: 1 }
|
||||
meta: { user_id: @user_id, tc: @id_seed }
|
||||
}
|
||||
MockWebApi.insertDoc @project_id, @doc.id, {
|
||||
lines: @doc.lines
|
||||
|
|
Loading…
Reference in a new issue