plugins/replicate/legacy.jsView |
---|
4 | 4 | var Notify = require('pull-notify') |
5 | 5 | var Cat = require('pull-cat') |
6 | 6 | var Debounce = require('observ-debounce') |
7 | 7 | var deepEqual = require('deep-equal') |
| 8 | +var Obv = require('obv') |
| 9 | +var isFeed = require('ssb-ref').isFeed |
8 | 10 | |
9 | 11 | var Pushable = require('pull-pushable') |
10 | 12 | |
11 | 13 | |
68 | 70 | var start = null |
69 | 71 | var count = 0 |
70 | 72 | var rate = 0 |
71 | 73 | var loadedFriends = false |
72 | | - var toSend = {} |
| 74 | + var toSend |
73 | 75 | var peerHas = {} |
74 | 76 | var pendingFeedsForPeer = {} |
75 | 77 | var lastProgress = null |
76 | 78 | |
| 79 | + var newPeers = Notify() |
| 80 | + var replicate = {} |
| 81 | + |
| 82 | + function request (id) { |
| 83 | + if(!replicate[id]) { |
| 84 | + replicate[id] = true |
| 85 | + newPeers({id:id, sequence: toSend[id] || 0}) |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + sbot.getVectorClock(function (err, clock) { |
| 90 | + if(err) throw err |
| 91 | + toSend = clock |
| 92 | + }) |
| 93 | + |
| 94 | + sbot.post(function (msg) { |
| 95 | + |
| 96 | + toSend[msg.value.author] = msg.value.sequence |
| 97 | + debounce.set() |
| 98 | + }) |
| 99 | + |
77 | 100 | debounce(function () { |
78 | 101 | |
79 | 102 | var feeds = loadedFriends ? Object.keys(toSend).length : null |
80 | 103 | var legacyProgress = 0 |
152 | 175 | p.push(e) |
153 | 176 | }) |
154 | 177 | } |
155 | 178 | count ++ |
156 | | - addPeer({id: e.author, sequence: e.sequence}) |
| 179 | + |
| 180 | + |
157 | 181 | }) |
158 | 182 | ) |
159 | 183 | |
| 184 | + var chs = sbot.createHistoryStream |
| 185 | + |
| 186 | + |
| 187 | + |
| 188 | + |
| 189 | + |
| 190 | + |
| 191 | + |
160 | 192 | sbot.createHistoryStream.hook(function (fn, args) { |
161 | 193 | var upto = args[0] || {} |
162 | 194 | var seq = upto.sequence || upto.seq |
163 | | - |
164 | 195 | if(this._emit) this._emit('call:createHistoryStream', args[0]) |
165 | 196 | |
166 | 197 | |
167 | 198 | if(this===sbot) return fn.call(this, upto) |
171 | 202 | peerHas[this.id][upto.id] = seq - 1 |
172 | 203 | |
173 | 204 | debounce.set() |
174 | 205 | |
175 | | - |
| 206 | + |
176 | 207 | |
177 | 208 | if(toSend[upto.id] == null || (seq > toSend[upto.id])) { |
178 | 209 | upto.old = false |
179 | 210 | if(!upto.live) return pull.empty() |
195 | 226 | opts.dunbar = opts.dunbar || 150 |
196 | 227 | opts.live = true |
197 | 228 | opts.meta = true |
198 | 229 | |
| 230 | + |
| 231 | + |
199 | 232 | function localPeers () { |
200 | 233 | if(!sbot.gossip) return |
201 | 234 | sbot.gossip.peers().forEach(function (e) { |
202 | 235 | if (e.source === 'local' && toSend[e.key] == null) { |
214 | 247 | var int = setInterval(localPeers, 1000) |
215 | 248 | if(int.unref) int.unref() |
216 | 249 | localPeers() |
217 | 250 | } |
| 251 | + |
218 | 252 | |
219 | 253 | function friendsLoaded () { |
220 | 254 | loadedFriends = true |
221 | 255 | debounce.set() |
222 | 256 | } |
223 | 257 | |
224 | | - function addPeer (upto) { |
225 | | - if(upto.sync) return friendsLoaded() |
226 | | - if(!upto.id) return console.log('invalid', upto) |
| 258 | + |
| 259 | + |
| 260 | + |
| 261 | + |
| 262 | + |
| 263 | + |
| 264 | + |
| 265 | + |
| 266 | + |
| 267 | + |
| 268 | + |
| 269 | + |
| 270 | + |
| 271 | + |
227 | 272 | |
228 | | - if(toSend[upto.id] == null) { |
229 | | - toSend[upto.id] = Math.max(toSend[upto.id] || 0, upto.sequence || upto.seq || 0) |
230 | | - newPeer({id: upto.id, sequence: toSend[upto.id] , type: 'new' }) |
231 | | - } else { |
232 | | - toSend[upto.id] = Math.max(toSend[upto.id] || 0, upto.sequence || upto.seq || 0) |
233 | | - } |
234 | | - |
235 | | - debounce.set() |
236 | | - } |
237 | | - |
238 | | - |
239 | 273 | |
240 | | - pull( |
241 | | - sbot.friends.createFriendStream(opts), |
242 | | - |
243 | | - |
244 | | - |
245 | | - pull.asyncMap(function (data, cb) { |
246 | | - if(data.sync) return cb(null, data) |
247 | | - var id = data.id || data |
248 | | - sbot.latestSequence(id, function (err, seq) { |
249 | | - cb(null, { |
250 | | - id: id, sequence: err ? 0 : toSeq(seq) |
251 | | - }) |
252 | | - }) |
253 | | - }, 32), |
254 | | - pull.drain(addPeer, friendsLoaded) |
255 | | - ) |
| 274 | + |
| 275 | + |
| 276 | + |
| 277 | + |
| 278 | + |
| 279 | + |
| 280 | + |
| 281 | + |
| 282 | + |
| 283 | + |
| 284 | + |
| 285 | + |
| 286 | + |
| 287 | + |
| 288 | + |
| 289 | + |
256 | 290 | |
257 | 291 | function upto (opts) { |
258 | 292 | opts = opts || {} |
259 | | - var ary = Object.keys(toSend).map(function (k) { |
260 | | - return { id: k, sequence: toSend[k] } |
| 293 | + var ary = Object.keys(replicate).map(function (k) { |
| 294 | + return { id: k, sequence: toSend[k]||0 } |
261 | 295 | }) |
262 | 296 | if(opts.live) |
263 | | - return Cat([pull.values(ary), pull.once({sync: true}), newPeer.listen()]) |
| 297 | + return Cat([ |
| 298 | + pull.values(ary), |
| 299 | + pull.once({sync: true}), |
| 300 | + newPeer.listen() |
| 301 | + ]) |
264 | 302 | |
265 | 303 | return pull.values(ary) |
266 | 304 | } |
267 | 305 | |
274 | 312 | |
275 | 313 | var drain |
276 | 314 | |
277 | 315 | function replicate(upto, cb) { |
278 | | - console.log(sbot.id.substring(0, 10), upto) |
279 | 316 | pendingFeedsForPeer[rpc.id] = pendingFeedsForPeer[rpc.id] || new Set() |
280 | 317 | pendingFeedsForPeer[rpc.id].add(upto.id) |
281 | 318 | |
282 | 319 | debounce.set() |
289 | 326 | sbot.createWriteStream(function (err) { |
290 | 327 | if(err && !(err.message in errorsSeen)) { |
291 | 328 | errorsSeen[err.message] = true |
292 | 329 | if(err.message in streamErrors) { |
293 | | - cb(err) |
| 330 | + cb && cb(err) |
294 | 331 | if(err.message === 'unexpected end of parent stream') { |
295 | 332 | if (err instanceof Error) { |
296 | 333 | |
297 | 334 | } else { |
300 | 337 | rpc.close(err) |
301 | 338 | } |
302 | 339 | } |
303 | 340 | } else { |
304 | | - console.error('Error replicating with ' + rpc.id + ':\n ', |
305 | | - err.stack) |
| 341 | + console.error( |
| 342 | + 'Error replicating with ' + rpc.id + ':\n ', |
| 343 | + err.stack |
| 344 | + ) |
306 | 345 | } |
307 | 346 | } |
308 | 347 | |
309 | 348 | pendingFeedsForPeer[rpc.id].delete(upto.id) |
324 | 363 | function fallback () { |
325 | 364 | |
326 | 365 | if(replicate_self) return |
327 | 366 | replicated_self = true |
328 | | - sbot.latestSequence(sbot.id, function (err, seq) { |
329 | | - replicate({ |
330 | | - id: sbot.id, sequence: err ? 0 : toSeq(seq) |
331 | | - }, function () {}) |
332 | | - }) |
| 367 | + |
| 368 | + replicate({id: sbot.id, sequence: toSend[sbot.id] || 0}) |
| 369 | + |
| 370 | + |
| 371 | + |
| 372 | + |
| 373 | + |
333 | 374 | } |
| 375 | + |
334 | 376 | |
335 | 377 | rpc.once('call:createHistoryStream', next) |
336 | 378 | |
| 379 | + var started = false |
337 | 380 | function next () { |
| 381 | + if(started) return |
| 382 | + started = true |
338 | 383 | sbot.emit('replicate:start', rpc) |
339 | 384 | |
340 | 385 | rpc.on('closed', function () { |
| 386 | + console.log(toSend) |
341 | 387 | sbot.emit('replicate:finish', toSend) |
342 | 388 | }) |
343 | 389 | |
| 390 | + |
344 | 391 | pull( |
345 | 392 | upto({live: opts.live}), |
346 | 393 | drain = pull.drain(function (upto) { |
347 | 394 | if(upto.sync) return |
| 395 | + if(!isFeed(upto.id)) throw new Error('expected feed!') |
| 396 | + if(!Number.isInteger(upto.sequence)) throw new Error('expected sequence!') |
| 397 | + |
348 | 398 | if(upto.id == sbot.id && replicate_self) return replicate_self = true |
349 | 399 | replicate(upto, function (err) { |
350 | 400 | drain.abort() |
351 | 401 | }) |
356 | 406 | ) |
357 | 407 | |
358 | 408 | } |
359 | 409 | }) |
360 | | - return upto |
| 410 | + |
| 411 | + return { |
| 412 | + request: request, |
| 413 | + upto: upto, |
| 414 | + changes: notify.listen |
| 415 | + } |
| 416 | + |
361 | 417 | } |
362 | 418 | |
363 | 419 | |
364 | 420 | |
365 | 421 | |
| 422 | + |