-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
77 lines (71 loc) · 2.93 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
// uuid/v4 is what pouchdb/utils uses
import uuid from 'uuid/v4'
import Checkpointer from 'pouchdb-checkpointer'
import generateReplicationId from 'pouchdb-generate-replication-id'
// Only try one shot if we've never seen this replication id.
export function maybeAllDocsReplicate (localDb, onProgressCallback) {
var remoteDb = this
return generateReplicationId(remoteDb, localDb, {})
.then(downloadRepId => {
return localDb.get(downloadRepId).catch(resp => {
return downloadReplication(remoteDb, localDb, downloadRepId, onProgressCallback)
.then(() => uploadReplication(remoteDb, localDb))
})
})
}
function downloadReplication (remoteDb, localDb, downloadRepId, onProgressCallback) {
return allDocsWithProgress(remoteDb, onProgressCallback)
.then(function (response) {
var docs = response.rows.map(row => row.doc)
return localDb.bulkDocs({ docs, new_edits: false })
.then(() => writeCheckpoint(remoteDb, localDb, downloadRepId, response.update_seq))
})
}
function uploadReplication(remoteDb, localDb) {
return generateReplicationId(localDb, remoteDb, {})
.then(uploadRepId => {
return remoteDb.get(uploadRepId).catch(() => {
return localDb.info().then((info) => {
return writeCheckpoint(localDb, remoteDb, uploadRepId, info.update_seq)
})
})
})
}
function writeCheckpoint (firstDb, secondDb, replicationId, seq_no) {
var options = { writeSourceCheckpoint: true, writeTargetCheckpoint: true }
var checkpointer = new Checkpointer(firstDb, secondDb, replicationId, {}, options)
var session = uuid()
return checkpointer.writeCheckpoint(seq_no, session)
}
// 1. Couch doesn't respond with a Content-length header on _all_docs, so we guestimate total download
// from info.disk_size, then on complete call onProgressCallback with total / total to fix.
// 2. Using XMLHttpRequest over pouch.allDocs() to get progress events on the one http request.
function allDocsWithProgress (remoteDb, onProgressCallback) {
return remoteDb.info().then(function (info) {
var total = info.disk_size
onProgressCallback(0, total)
var url = remoteDb.__opts.name + '/_all_docs?include_docs=true&update_seq=true'
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.addEventListener('error', function (error) { reject(error) })
xhr.addEventListener('abort', function (error) { reject(error) })
xhr.addEventListener('progress', function (event) {
if (xhr.status < 400) {
onProgressCallback(event.loaded, total)
}
})
xhr.addEventListener('load', function () {
if (xhr.status >= 400) {
reject(xhr.responseText)
} else {
onProgressCallback(total, total)
var response = JSON.parse(xhr.responseText)
resolve(response)
}
})
xhr.open('GET', url)
xhr.send()
})
})
}