My Code
thats is a short version of my current code.:
['tableA', 'tableB', 'tableC'].forEach(name => {
let local = new PouchDB(name, { auto_compaction: true })
let server = new PouchDB(serverUrl + name)
var filtro = {
include_docs: true,
filter: 'replication/by_dispositivo',
query_params: { 'dispositivo_id': obj.deviceId }
}
local.replicate.from(server, filtro).on('complete', report => {
var sync = local.sync(server, {
live: true,
retry: true,
...filtro
})
})
})
I'm trying to do a live replication, but for some reason, that doesn't replicate the local data to the server, strangely, PouchDb didn't throw any exception.
Inspecting the Network tab on Dev Tools, I can see te follow request.:
URL: ${serverUrl}/{name}/_revs_diff
Response: {
"4b0ea507-cd88-4998-baf0-01629b50516b": {
"missing": [
"2-2133d30de8d44ebd958cee2b68726ffb"
],
"possible_ancestors": [
"1-39904a7e55b1cb266c840a2acf34fdc2"
]
}
}
Ok, PouchDb detected that something is missing in the server and must be replicated.
Auditing the Sync
Searching for a hint about what is happening, I modified my code to log the complete and error events.:
['tableA', 'tableB', 'tableC'].forEach(name => {
let local = new PouchDB(name, { auto_compaction: true })
let server = new PouchDB(serverUrl + name)
let filtro = {
include_docs: true,
filter: 'replication/by_dispositivo',
query_params: { 'dispositivo_id': obj.deviceId }
}
local.replicate.from(server, filtro).on('complete', report => {
let sync = local.sync(server, {
live: true,
retry: true,
...filtro
})
sync.on('error', (error) => {
console.error(error)
console.error(JSON.stringify(error, null, 2))
}).on('complete', (result) => {
console.log(result)
console.log(JSON.stringify(result, null, 2))
})
window.setTimeout(function (evt) {
state.syncProcess[database].cancel()
}, 15000)
})
})
I didn't catch anything in the error event, and the complete event didn't show any errors as you can see bellow.
{
"push": {
"ok": true,
"start_time": "2018-04-06T15:00:42.266Z",
"docs_read": 0,
"docs_written": 0,
"doc_write_failures": 0,
"errors": [],
"status": "cancelled",
"end_time": "2018-04-06T15:00:42.266Z",
"last_seq": 0
},
"pull": {
"ok": true,
"start_time": "2018-04-06T15:00:26.422Z",
"docs_read": 0,
"docs_written": 0,
"doc_write_failures": 0,
"errors": [],
"last_seq": "17-g1AAAAJDeJyd0EsOgjAQBuAqJj52nkCPILGldCU3UaYzBA3CQl3rTfQmehO9CRZKAiaGiJtpMs18mX8SxtgodpBNdXbSMUKQZDpM4uxwTMxXP2Qwy_N8Fzsh25vGMILIA62QjU8pUrRNCVvGYW4qrCphUgoCfMVd_W2mTQoKaV1JjpWWIUcuu0qbQjp_pBKeUESLH1OlA1PZxTwGudb7EC1dQt5xH6vdrHYvtF6pSZK-4Oov7WG1Z53QUy56UnRK-LJK406-TxIAm8ruDdzts44",
"status": "cancelled",
"end_time": "2018-04-06T15:00:41.427Z"
}
}
Calling one time local to server replication manually
that is my second attempt to catch something usefull. I trying to audit the local.replicate.to method
['tableA', 'tableB', 'tableC'].forEach(name => {
let local = new PouchDB(name, { auto_compaction: true })
let server = new PouchDB(serverUrl + name)
let filtro = {
include_docs: true,
filter: 'replication/by_dispositivo',
query_params: { 'dispositivo_id': obj.deviceId }
}
local.replicate.from(server, filtro).on('complete', report => {
local.replicate.to(server, filtro).on('complete', report => {
console.log(report)
console.log(JSON.stringify(report, null, 2))
let sync = local.sync(server, {
live: true,
retry: true,
...filtro
})
}).on('error', (error) => {
console.error(error)
console.error(JSON.stringify(error, null, 2))
})
})
})
thats time complete event isn't fired and I catch a error, but that is too generic amd don't give any clues regarding whats is happening.
{
"result": {
"ok": false,
"start_time": "2018-04-06T15:07:19.105Z",
"docs_read": 1,
"docs_written": 0,
"doc_write_failures": 0,
"errors": [],
"status": "aborting",
"end_time": "2018-04-06T15:07:19.768Z",
"last_seq": 3
}
}
Putting local data to the server
thats is my last attempt.:
- I'll query local and remote databases (in that particular case, I have only one document)
- Copy fields from local doc to remote doc.
- Dispatch the updated remote doc to the remote database
My Junk Code
var deviceId = ''
var listLocal = []
var listServer = []
getDeviceId().then(response => {
deviceId = response
return local.find({ selector: { dispositivo_id: deviceId } })
}).then(response => {
listLocal = response.docs
return server.find({ selector: { dispositivo_id: deviceId } })
}).then(response => {
listServer = response.docs
var tlocal = listLocal[0]
var tServer = listServer[0]
Object.keys(tServer).forEach(key => {
if (key.indexOf("_") !== 0) {
tServer[key] = undefined
}
})
Object.keys(tlocal).forEach(key => {
if (key.indexOf("_") !== 0) {
tServer[key] = tlocal[key]
}
})
return server.put(tServer).then(result => {
console.log(result)
console.log(JSON.stringify(result, null, 2))
}).catch(error => {
console.error(error)
console.error(JSON.stringify(error, null, 2))
})
})
The junk code worked as expected, and i received that response.:
{
"ok": true,
"id": "4b0ea507-cd88-4998-baf0-01629b50516b",
"rev": "2-d9363f28e53fdc145610f5ad3f75a043"
}
Additional Information
My design documents in the CouchDb
_design/replication
{
"_id": "_design/replication",
"_rev": "1-42df919aaee8ed3fb309bbda999ba03d",
"language": "javascript",
"filters": {
"by_dispositivo": "function(doc, req) {\r\n return doc._id === '_design/replication' || (doc.dispositivo_id === req.query.dispositivo_id && !doc._deleted)\r\n}",
"by_situacao_remote": "function(doc, req) {\r\n return [2, 3, 4, 5].indexOf(doc.situacao) !== -1 && !doc._deleted\r\n}"
}
}
_design/authorization
{
"_id": "_design/authorization",
"_rev": "9-64c4a22645d783c9089c95d69e9424ad",
"language": "javascript",
"validate_doc_update": "..."
}
authorization/validate_doc_update
function(newDoc, oldDoc, userCtx) {
var isAdmin = userCtx.roles.indexOf('_admin') !== -1 || userCtx.roles.indexOf('admin') !== -1;
if (!isAdmin) {
if (newDoc._deleted) {
if (oldDoc.dispositivo_id !== userCtx.name) {
throw({forbidden: "..." });
}
}
else {
if (!newDoc.dispositivo_id || !newDoc.dispositivo_id.trim())
throw({forbidden: "..." });
if (newDoc.dispositivo_id !== userCtx.name) {
throw({forbidden: "..." });
}
if (oldDoc && oldDoc.dispositivo_id !== userCtx.name) {
throw({forbidden: "..." });
}
var isRequired = function (prop, msg) {
var value = newDoc[prop];
if (!value)
throw({forbidden: '...' });
}
var isDate = function (prop, msg, allow_null) {
if (!allow_null)
isRequired(prop, msg)
var value = newDoc[prop];
if (value) {
var date = new Date(value);
var isDate = date !== "Invalid Date" && !isNaN(date);
if (!isDate) {
throw({forbidden: msg });
}
}
}
var isFloat = function (prop, msg, allow_null) {
if (!allow_null)
isRequired(prop, msg)
var value = newDoc[prop];
if (value) {
var numero = new Number(value);
if (!numero || isNaN(numero) || !isFinite(numero)) {
throw({forbidden: msg });
}
}
}
var isInteger = function (prop, msg, allow_null) {
isFloat(prop, msg, allow_null)
var value = newDoc[prop];
if (value) {
var numero = new Number(value);
var isInteger = Math.floor(numero) == numero;
if (!isInteger) {
throw({forbidden: msg });
}
}
}
isRequired("talao_id", "...");
isRequired("equipe_id", "...");
isInteger("situacao", '...');
isDate("data_envio", "...");
isDate("data_recebimento", "...", true);
isDate("data_decisao", "...", true);
isRequired("tipo_ocorrencia_codigo", "...");
isRequired("tipo_ocorrencia_descricao", "...");
isInteger("talao_codigo", "...");
isRequired("talao_descricao", "...");
isRequired("talao_solicitante", "...");
isRequired("talao_endereco", "...");
}
}
else if (!newDoc._deleted) {
if (!newDoc.dispositivo_id || !newDoc.dispositivo_id.trim())
throw({forbidden: "..." });
}
}