Last active
March 12, 2018 14:53
-
-
Save chefnobody/5f35ca9c3a36dc1664bcea97b6bdfdec to your computer and use it in GitHub Desktop.
Notes from reading through Peer-to-Peer white boarding article from Black Pixel.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
/* | |
Peer-to-Peer white boarding application: | |
https://medium.com/bpxl-craft/building-a-peer-to-peer-whiteboarding-app-for-ipad-2a4c7728863e | |
Conflict-Free Replicated Data Type | |
CRDT | |
https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type#cite_note-OsterUrso2006-4 | |
*/ | |
/* | |
Edits are “conflict free” in that Pixelboard’s Edit integration algorithm guarantees that any Edit can be applied to a Drawing in any order and will always produce a valid result. | |
From the article: | |
Networks can be slow and unreliable. EditRecords cannot be guaranteed to be received in the same order in which they were created, nor can we guarantee that a device won’t receive the same EditRecord twice. Thus, sets of EditRecords must exhibit the following properties: | |
Associativity: (A∪B)∪C=A∪(B∪C) The order of the union operations must not matter, so that multiple sets of EditRecords from other devices in a session can be integrated in whatever order the network conditions allow. | |
Commutativity: A∪B=B∪A The order of the arguments to a union operation of two EditRecord sets must not affect the resulting value. | |
Idempotence: A∪A=A Duplicate EditRecords must be able to be integrated more than once without leading to duplication of those records in the replicated set of all records, nor duplicated information in the computed Drawing. | |
*/ | |
indirect enum Edit { | |
case addStroke(Stroke) | |
case undo(Edit) | |
case redo(Edit) | |
} | |
typealias LogicalTimestamp = Int64 | |
typealias UnixTimestamp = Int64 | |
typealias CollaboratorID = Int64 | |
struct EditRecord: Hashable, Comparable, Codable { | |
let edit: Edit | |
let logicalTimestamp: LogicalTimestamp | |
let temporalTimestamp: UnixTimestamp | |
let collaboratorID: CollaboratorID | |
static func < (lhs: EditRecord, rhs: EditRecord) -> Bool { | |
if lhs.logicalTimestamp != rhs.logicalTimestamp { | |
return lhs.logicalTimestamp < rhs.logicalTimestamp | |
} | |
else if lhs.temporalTimestamp != rhs.temporalTimestamp { | |
// more helpful as a tie-breaker when a logical time stamp | |
// match is found. | |
return lhs.temporalTimestamp < rhs.temporalTimestamp | |
} | |
else { | |
return lhs.collaboratorId < rhs.collaboratorId | |
} | |
} | |
} | |
struct Stroke { | |
} | |
struct Drawing { | |
let strokes: [Stroke] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment