mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-03-30 15:08:28 +00:00
docs: Lamport clock docs. (#77)
* docs: Lamport clock docs. * docs: Formatting. * docs: Formatting. * docs: Formatting.
This commit is contained in:
parent
b9e573dc6d
commit
bd6bb021c1
@ -44,8 +44,8 @@ const PublicKeyIdentityProvider = ({ keystore }) => {
|
||||
/**
|
||||
* Gets the id.
|
||||
* @memberof module:IdentityProviders.IdentityProvider-PublicKey
|
||||
* @param {String} id The id to retrieve.
|
||||
* @return {String} The identity's id.
|
||||
* @param {string} id The id to retrieve.
|
||||
* @return {string} The identity's id.
|
||||
* @instance
|
||||
*/
|
||||
const getId = async ({ id } = {}) => {
|
||||
|
@ -1,4 +1,19 @@
|
||||
/* Lamport Clock */
|
||||
/**
|
||||
* @module Clock
|
||||
* @description
|
||||
* The lamport clock.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compares two clocks by time and then, time is the same, by id.
|
||||
*
|
||||
* compareClocks should never return zero (0). If it does, a and b refer to the
|
||||
* same clock.
|
||||
* @param {module:Clock} a The first clock.
|
||||
* @param {module:Clock} b The second clock.
|
||||
* @return {number} Returns a negative integer if clock a is less than clock b
|
||||
* otherwise a positive integer is returned.
|
||||
*/
|
||||
const compareClocks = (a, b) => {
|
||||
// Calculate the "distance" based on the clock, ie. lower or greater
|
||||
const dist = a.time - b.time
|
||||
@ -10,10 +25,22 @@ const compareClocks = (a, b) => {
|
||||
return dist
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances a clock's time by 1, returning a new instance of Clock.
|
||||
* @param {module:Clock} clock The clock to advance.
|
||||
* @return {module:Clock} A new instance of clock with time advanced by 1.
|
||||
*/
|
||||
const tickClock = (clock) => {
|
||||
return Clock(clock.id, ++clock.time)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of Clock.
|
||||
* @function
|
||||
* @param {string} id A unique identifier.
|
||||
* @param {number} [time=0] A natural number (including 0).
|
||||
* @instance
|
||||
*/
|
||||
const Clock = (id, time) => {
|
||||
time = time || 0
|
||||
|
||||
|
@ -26,7 +26,10 @@ function LastWriteWins (a, b) {
|
||||
* Sort two entries by their clock time.
|
||||
* @param {Entry} a First entry to compare
|
||||
* @param {Entry} b Second entry to compare
|
||||
* @param {function(a, b)} resolveConflict A function to call if entries are concurrent (happened at the same time). The function should take in two entries and return 1 if the first entry should be chosen and -1 if the second entry should be chosen.
|
||||
* @param {function(a, b)} resolveConflict A function to call if entries are
|
||||
* concurrent (happened at the same time). The function should take in two
|
||||
* entries and return 1 if the first entry should be chosen and -1 if the
|
||||
* second entry should be chosen.
|
||||
* @return {number} 1 if a is greater, -1 if b is greater
|
||||
*/
|
||||
function SortByClocks (a, b, resolveConflict) {
|
||||
@ -41,7 +44,9 @@ function SortByClocks (a, b, resolveConflict) {
|
||||
* Sort two entries by their clock id.
|
||||
* @param {Entry} a First entry to compare
|
||||
* @param {Entry} b Second entry to compare
|
||||
* @param {function(a, b)} resolveConflict A function to call if the clocks ids are the same. The function should take in two entries and return 1 if the first entry should be chosen and -1 if the second entry should be chosen.
|
||||
* @param {function(a, b)} resolveConflict A function to call if the clocks ids
|
||||
* are the same. The function should take in two entries and return 1 if the
|
||||
* first entry should be chosen and -1 if the second entry should be chosen.
|
||||
* @return {number} 1 if a is greater, -1 if b is greater
|
||||
*/
|
||||
function SortByClockId (a, b, resolveConflict) {
|
||||
@ -53,7 +58,8 @@ function SortByClockId (a, b, resolveConflict) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper function to throw an error if the results of a passed function return zero
|
||||
* A wrapper function to throw an error if the results of a passed function
|
||||
* return zero
|
||||
* @param {function(a, b)} [tiebreaker] The tiebreaker function to validate.
|
||||
* @return {function(a, b)} 1 if a is greater, -1 if b is greater
|
||||
* @throws {Error} if func ever returns 0
|
||||
|
@ -17,10 +17,13 @@ const hashStringEncoding = base58btc
|
||||
* Create an Entry
|
||||
* @param {Identity} identity The identity instance
|
||||
* @param {string} logId The unique identifier for this log
|
||||
* @param {*} data Data of the entry to be added. Can be any JSON.stringifyable data
|
||||
* @param {Clock} [clock] The clock
|
||||
* @param {Array<string|Entry>} [next=[]] An array of CIDs as base58btc encoded strings
|
||||
* @param {Array<string|Entry>} [refs=[]] An array of CIDs as base58btc encoded strings
|
||||
* @param {*} data Data of the entry to be added. Can be any JSON.stringifyable
|
||||
* data.
|
||||
* @param {module:Clock} [clock] The clock
|
||||
* @param {Array<string|Entry>} [next=[]] An array of CIDs as base58btc encoded
|
||||
* strings.
|
||||
* @param {Array<string|Entry>} [refs=[]] An array of CIDs as base58btc encoded
|
||||
* strings.
|
||||
* @return {Promise<Entry>}
|
||||
* @example
|
||||
* const entry = await Entry.create(identity, 'log1', 'hello')
|
||||
@ -59,7 +62,8 @@ const create = async (identity, id, payload, clock = null, next = [], refs = [])
|
||||
*
|
||||
* @param {Identities} identities Identities system to use
|
||||
* @param {Entry} entry The entry being verified
|
||||
* @return {Promise} A promise that resolves to a boolean value indicating if the signature is valid
|
||||
* @return {Promise} A promise that resolves to a boolean value indicating if
|
||||
* the signature is valid.
|
||||
*/
|
||||
const verify = async (identities, entry) => {
|
||||
if (!identities) throw new Error('Identities is required, cannot verify entry')
|
||||
|
@ -45,7 +45,7 @@ const DefaultAccessController = async () => {
|
||||
* @param {Object} options.access AccessController (./default-access-controller)
|
||||
* @param {Array<Entry>} options.entries An Array of Entries from which to create the log
|
||||
* @param {Array<Entry>} options.heads Set the heads of the log
|
||||
* @param {Clock} options.clock Set the clock of the log
|
||||
* @param {module:Clock} options.clock Set the clock of the log
|
||||
* @param {Function} options.sortFn The sort function - by default LastWriteWins
|
||||
* @return {module:Log~Log} sync An instance of Log
|
||||
* @memberof module:Log
|
||||
@ -80,7 +80,7 @@ const Log = async (identity, { logId, logHeads, access, entryStorage, headsStora
|
||||
|
||||
/**
|
||||
* Returns the clock of the log.
|
||||
* @return {Clock}
|
||||
* @return {module:Clock}
|
||||
* @memberof module:Log~Log
|
||||
* @instance
|
||||
*/
|
||||
|
47
src/sync.js
47
src/sync.js
@ -18,26 +18,29 @@ const DefaultTimeout = 30000 // 30 seconds
|
||||
* When Sync is started, a peer subscribes to a pubsub topic of the log's id.
|
||||
* Upon subscribing to the topic, peers already connected to the topic receive
|
||||
* the subscription message and "dial" the subscribing peer using a libp2p
|
||||
* custom protocol. Once connected to the subscribing peer on a direct peer-to-peer
|
||||
* connection, the dialing peer and the subscribing peer exchange the heads of the Log
|
||||
* each peer currently has. Once completed, the peers have the same "local state".
|
||||
* custom protocol. Once connected to the subscribing peer on a direct
|
||||
* peer-to-peer connection, the dialing peer and the subscribing peer exchange * the heads of the Log each peer currently has. Once completed, the peers have * the same "local state".
|
||||
*
|
||||
* Once the initial sync has completed, peers notify one another of updates to the
|
||||
* log, ie. updates to the database, using the initially opened pubsub topic subscription.
|
||||
* A peer with new heads broadcasts changes to other peers by publishing the updated heads
|
||||
* to the pubsub topic. Peers subscribed to the same topic will then receive the update and
|
||||
* Once the initial sync has completed, peers notify one another of updates to
|
||||
* the log, ie. updates to the database, using the initially opened pubsub
|
||||
* topic subscription.
|
||||
* A peer with new heads broadcasts changes to other peers by publishing the
|
||||
* updated heads
|
||||
* to the pubsub topic. Peers subscribed to the same topic will then receive
|
||||
* the update and
|
||||
* will update their log's state, the heads, accordingly.
|
||||
*
|
||||
* The Sync Protocol is eventually consistent. It guarantees that once all messages
|
||||
* have been sent and received, peers will observe the same log state and values.
|
||||
* The Sync Protocol does not guarantee the order in which messages are received or
|
||||
* even that a message is recieved at all, nor any timing on when messages are received.
|
||||
* The Sync Protocol is eventually consistent. It guarantees that once all
|
||||
* messages have been sent and received, peers will observe the same log state
|
||||
* and values. The Sync Protocol does not guarantee the order in which messages
|
||||
* are received or even that a message is recieved at all, nor any timing on
|
||||
* when messages are received.
|
||||
*
|
||||
* Note that the Sync Protocol does not retrieve the full log when synchronizing the
|
||||
* heads. Rather only the "latest entries" in the log, the heads, are exchanged. In order
|
||||
* to retrieve the full log and each entry, the user would call the log.traverse() or
|
||||
* log.iterator() functions, which go through the log and retrieve each missing
|
||||
* log entry from IPFS.
|
||||
* Note that the Sync Protocol does not retrieve the full log when
|
||||
* synchronizing the heads. Rather only the "latest entries" in the log, the
|
||||
* heads, are exchanged. In order to retrieve the full log and each entry, the
|
||||
* user would call the log.traverse() or log.iterator() functions, which go
|
||||
* through the log and retrieve each missing log entry from IPFS.
|
||||
*
|
||||
* @example
|
||||
* // Using defaults
|
||||
@ -59,11 +62,13 @@ const DefaultTimeout = 30000 // 30 seconds
|
||||
* @param {Object} params One or more parameters for configuring Sync.
|
||||
* @param {IPFS} params.ipfs An IPFS instance.
|
||||
* @param {Log} params.log The log instance to sync.
|
||||
* @param {EventEmitter} [params.events] An event emitter to use. Events emitted are 'join', 'leave' and 'error'. If the parameter is not provided, an EventEmitter will be created.
|
||||
* @param {onSynced} [params.onSynced] A callback function that is called after the peer
|
||||
* has received heads from another peer.
|
||||
* @param {Boolean} [params.start] True if sync should start automatically, false
|
||||
* otherwise. Defaults to true.
|
||||
* @param {EventEmitter} [params.events] An event emitter to use. Events
|
||||
* emitted are 'join', 'leave' and 'error'. If the parameter is not provided,
|
||||
* an EventEmitter will be created.
|
||||
* @param {onSynced} [params.onSynced] A callback function that is called after
|
||||
* the peer has received heads from another peer.
|
||||
* @param {Boolean} [params.start] True if sync should start automatically,
|
||||
* false otherwise. Defaults to true.
|
||||
* @return {module:Sync~Sync} sync An instance of the Sync Protocol.
|
||||
* @memberof module:Sync
|
||||
* @instance
|
||||
|
Loading…
x
Reference in New Issue
Block a user