-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
146 lines (114 loc) · 3.17 KB
/
index.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
var Scuttlebutt = require("scuttlebutt")
var extend = require("xtend")
var LRU = require("lru-cache")
var filter = Scuttlebutt.filter
var DAY = 1000 * 60 * 60 * 24
var defaults = {
max: 500
, maxAge: DAY
}
module.exports = ExpiryModel
function ExpiryModel(options) {
options = extend({}, defaults, options || {})
if (!options.dispose) {
options.dispose = dispose
}
var scuttle = Scuttlebutt()
var maxAge = options.maxAge
var store = LRU(options)
scuttle.set = set
scuttle.get = get
scuttle.applyUpdate = applyUpdate
scuttle.toJSON = toJSON
scuttle.history = history
return scuttle
function dispose(key, value) {
var source = value[2]
var found = false
store.forEach(function (record) {
if (record[2] === source && record[1] !== value[1]) {
found = true
}
})
if (!found) {
delete scuttle.sources[source]
}
}
function set(key, value) {
scuttle.localUpdate([key, value])
}
function get(key) {
var record = store.get(key)
return record ? record[0][1] : null
}
function getMergedRecord(update) {
var transaction = update[0]
var key = transaction[0]
var current = store.get(key)
if (!current) {
return update.slice()
}
var currentValue = current[0][1]
var currentTs = current[1]
var value = transaction[1]
var ts = update[1]
if (typeof currentValue === "object" &&
typeof value === "object" && value !== null
) {
if (currentTs > ts) {
value = extend({}, value, currentValue)
} else {
value = extend({}, currentValue, value)
}
} else if (currentTs > ts) {
return false
}
return [[key, value], ts, update[2]]
}
function applyUpdate(update) {
var ts = update[1]
var key = update[0][0]
if (ts <= Date.now() - maxAge) {
return false
}
var record = getMergedRecord(update)
if (record === false) {
return false
} else if (record[0][1] === null) {
store.del(key)
} else {
store.set(key, record)
}
scuttle.emit("update", record[0][0], record[0][1]
, record[1], record[2])
return true
}
function toJSON() {
var hash = {}
store.forEach(function (record, key) {
hash[key] = record[0][1]
})
return hash
}
function history(sources) {
sources = sources || {}
var list = []
var now = Date.now()
store.forEach(function (record, key) {
var ts = record[1]
if (ts > now - maxAge) {
if (filter(record, sources)) {
list.push(record)
}
} else {
store.del(key)
}
})
return list.sort(function (a, b) {
if (a[2] !== b[2]) {
return 0
}
return a[1] < b[1] ? -1 : 1
})
}
}