This repository has been archived by the owner on Sep 30, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 55
/
log-sorting.js
99 lines (90 loc) · 3.76 KB
/
log-sorting.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
'use strict'
const Clock = require('./lamport-clock')
/**
* Sort two entries as Last-Write-Wins (LWW).
*
* Last Write Wins is a conflict resolution strategy for sorting elements
* where the element with a greater clock (latest) is chosen as the winner.
*
* @param {Entry} a First entry
* @param {Entry} b Second entry
* @returns {number} 1 if a is latest, -1 if b is latest
*/
function LastWriteWins (a, b) {
// Ultimate conflict resolution (take the first/left arg)
const First = (a, b) => a
// Sort two entries by their clock id, if the same always take the first
const sortById = (a, b) => SortByClockId(a, b, First)
// Sort two entries by their clock time, if concurrent,
// determine sorting using provided conflict resolution function
const sortByEntryClocks = (a, b) => SortByClocks(a, b, sortById)
// Sort entries by clock time as the primary sort criteria
return sortByEntryClocks(a, b)
}
/**
* Sort two entries by their hash.
*
* @param {Entry} a First entry
* @param {Entry} b Second entry
* @returns {number} 1 if a is latest, -1 if b is latest
*/
function SortByEntryHash (a, b) {
// Ultimate conflict resolution (compare hashes)
const compareHash = (a, b) => a.hash < b.hash ? -1 : 1
// Sort two entries by their clock id, if the same then compare hashes
const sortById = (a, b) => SortByClockId(a, b, compareHash)
// Sort two entries by their clock time, if concurrent,
// determine sorting using provided conflict resolution function
const sortByEntryClocks = (a, b) => SortByClocks(a, b, sortById)
// Sort entries by clock time as the primary sort criteria
return sortByEntryClocks(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.
* @returns {number} 1 if a is greater, -1 if b is greater
*/
function SortByClocks (a, b, resolveConflict) {
// Compare the clocks
const diff = Clock.compare(a.clock, b.clock)
// If the clocks are concurrent, use the provided
// conflict resolution function to determine which comes first
return diff === 0 ? resolveConflict(a, b) : diff
}
/**
* 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.
* @returns {number} 1 if a is greater, -1 if b is greater
*/
function SortByClockId (a, b, resolveConflict) {
// Sort by ID if clocks are concurrent,
// take the entry with a "greater" clock id
return a.clock.id === b.clock.id
? resolveConflict(a, b)
: a.clock.id < b.clock.id ? -1 : 1
}
/**
* 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.
* @returns {function(a, b)} 1 if a is greater, -1 if b is greater
* @throws {Error} if func ever returns 0
*/
function NoZeroes (func) {
const msg = `Your log's tiebreaker function, ${func.name}, has returned zero and therefore cannot be`
const comparator = (a, b) => {
// Validate by calling the function
const result = func(a, b)
if (result === 0) { throw Error(msg) }
return result
}
return comparator
}
exports.SortByClocks = SortByClocks
exports.SortByClockId = SortByClockId
exports.LastWriteWins = LastWriteWins
exports.SortByEntryHash = SortByEntryHash
exports.NoZeroes = NoZeroes