mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-01 19:59:09 -05: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)
|
rangesTracker = new RangesTracker(changes, comments)
|
||||||
for update in updates
|
for update in updates
|
||||||
rangesTracker.track_changes = !!update.meta.tc
|
rangesTracker.track_changes = !!update.meta.tc
|
||||||
|
if !!update.meta.tc
|
||||||
|
rangesTracker.setIdSeed(update.meta.tc)
|
||||||
for op in update.op
|
for op in update.op
|
||||||
rangesTracker.applyOp(op, { user_id: update.meta?.user_id })
|
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
|
# * 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.
|
# middle of a previous insert by the first user, the original insert will be split into two.
|
||||||
constructor: (@changes = [], @comments = []) ->
|
constructor: (@changes = [], @comments = []) ->
|
||||||
# Change objects have the following structure:
|
|
||||||
# {
|
getIdSeed: () ->
|
||||||
# id: ... # Uniquely generated by us
|
return @id_seed
|
||||||
# op: { # ShareJs style op tracking the offset (p) and content inserted (i) or deleted (d)
|
|
||||||
# i: "..."
|
setIdSeed: (seed) ->
|
||||||
# p: 42
|
@id_seed = seed
|
||||||
# }
|
@id_increment = 0
|
||||||
# }
|
|
||||||
#
|
newId: () ->
|
||||||
# Ids are used to uniquely identify a change, e.g. for updating it in the database, or keeping in
|
@id_increment++
|
||||||
# sync with Ace ranges.
|
increment = @id_increment.toString(16)
|
||||||
@id = 0
|
id = @id_seed + '000000'.substr(0, 6 - increment.length) + increment;
|
||||||
|
return id
|
||||||
|
|
||||||
getComment: (comment_id) ->
|
getComment: (comment_id) ->
|
||||||
comment = null
|
comment = null
|
||||||
|
@ -56,19 +57,6 @@ load = (EventEmitter) ->
|
||||||
break
|
break
|
||||||
return comment
|
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) ->
|
removeCommentId: (comment_id) ->
|
||||||
comment = @getComment(comment_id)
|
comment = @getComment(comment_id)
|
||||||
return if !comment?
|
return if !comment?
|
||||||
|
@ -88,7 +76,7 @@ load = (EventEmitter) ->
|
||||||
return if !change?
|
return if !change?
|
||||||
@_removeChange(change)
|
@_removeChange(change)
|
||||||
|
|
||||||
applyOp: (op, metadata) ->
|
applyOp: (op, metadata = {}) ->
|
||||||
metadata.ts ?= new Date()
|
metadata.ts ?= new Date()
|
||||||
# Apply an op that has been applied to the document to our changes to keep them up to date
|
# Apply an op that has been applied to the document to our changes to keep them up to date
|
||||||
if op.i?
|
if op.i?
|
||||||
|
@ -105,7 +93,7 @@ load = (EventEmitter) ->
|
||||||
addComment: (op, metadata) ->
|
addComment: (op, metadata) ->
|
||||||
# TODO: Don't allow overlapping comments?
|
# TODO: Don't allow overlapping comments?
|
||||||
@comments.push comment = {
|
@comments.push comment = {
|
||||||
id: @_newId()
|
id: @newId()
|
||||||
op: # Copy because we'll modify in place
|
op: # Copy because we'll modify in place
|
||||||
c: op.c
|
c: op.c
|
||||||
p: op.p
|
p: op.p
|
||||||
|
@ -394,28 +382,9 @@ load = (EventEmitter) ->
|
||||||
if moved_changes.length > 0
|
if moved_changes.length > 0
|
||||||
@emit "changes:moved", moved_changes
|
@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) ->
|
_addOp: (op, metadata) ->
|
||||||
change = {
|
change = {
|
||||||
id: @_newId()
|
id: @newId()
|
||||||
op: op
|
op: op
|
||||||
metadata: metadata
|
metadata: metadata
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ describe "Ranges", ->
|
||||||
before (done) ->
|
before (done) ->
|
||||||
@project_id = DocUpdaterClient.randomId()
|
@project_id = DocUpdaterClient.randomId()
|
||||||
@user_id = DocUpdaterClient.randomId()
|
@user_id = DocUpdaterClient.randomId()
|
||||||
|
@id_seed = "587357bd35e64f6157"
|
||||||
@doc = {
|
@doc = {
|
||||||
id: DocUpdaterClient.randomId()
|
id: DocUpdaterClient.randomId()
|
||||||
lines: ["aaa"]
|
lines: ["aaa"]
|
||||||
|
@ -25,7 +26,7 @@ describe "Ranges", ->
|
||||||
doc: @doc.id
|
doc: @doc.id
|
||||||
op: [{ i: "456", p: 5 }]
|
op: [{ i: "456", p: 5 }]
|
||||||
v: 1
|
v: 1
|
||||||
meta: { user_id: @user_id, tc: 1 }
|
meta: { user_id: @user_id, tc: @id_seed }
|
||||||
}, {
|
}, {
|
||||||
doc: @doc.id
|
doc: @doc.id
|
||||||
op: [{ d: "12", p: 1 }]
|
op: [{ d: "12", p: 1 }]
|
||||||
|
@ -52,6 +53,7 @@ describe "Ranges", ->
|
||||||
ranges = data.ranges
|
ranges = data.ranges
|
||||||
change = ranges.changes[0]
|
change = ranges.changes[0]
|
||||||
change.op.should.deep.equal { i: "456", p: 3 }
|
change.op.should.deep.equal { i: "456", p: 3 }
|
||||||
|
change.id.should.equal @id_seed + "000001"
|
||||||
change.metadata.user_id.should.equal @user_id
|
change.metadata.user_id.should.equal @user_id
|
||||||
done()
|
done()
|
||||||
|
|
||||||
|
@ -135,6 +137,7 @@ describe "Ranges", ->
|
||||||
before (done) ->
|
before (done) ->
|
||||||
@project_id = DocUpdaterClient.randomId()
|
@project_id = DocUpdaterClient.randomId()
|
||||||
@user_id = DocUpdaterClient.randomId()
|
@user_id = DocUpdaterClient.randomId()
|
||||||
|
@id_seed = "587357bd35e64f6157"
|
||||||
@doc = {
|
@doc = {
|
||||||
id: DocUpdaterClient.randomId()
|
id: DocUpdaterClient.randomId()
|
||||||
lines: ["a123aa"]
|
lines: ["a123aa"]
|
||||||
|
@ -143,7 +146,7 @@ describe "Ranges", ->
|
||||||
doc: @doc.id
|
doc: @doc.id
|
||||||
op: [{ i: "456", p: 5 }]
|
op: [{ i: "456", p: 5 }]
|
||||||
v: 0
|
v: 0
|
||||||
meta: { user_id: @user_id, tc: 1 }
|
meta: { user_id: @user_id, tc: @id_seed }
|
||||||
}
|
}
|
||||||
MockWebApi.insertDoc @project_id, @doc.id, {
|
MockWebApi.insertDoc @project_id, @doc.id, {
|
||||||
lines: @doc.lines
|
lines: @doc.lines
|
||||||
|
|
Loading…
Reference in a new issue