Fail while replicating data from PouchDb to CouchDb - javascript

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: "..." });
}
}

While analyzing the stack trace of the exception throw by local.replicate.to, I noticied that reason: promise.all is not a function.
So i googled for a while and found that topic Webpack: Promise is not a constructor. I just need to copy the workaround bellow to my webpack.config and everything worked like a charm.:
resolve: {
alias: {
'pouchdb-promise$': "pouchdb-promise/lib/index.js"
}
}

Related

web service is called several times

I have a web service which is called 3 times and I don't know why ?
This is the web service WLOLBLOK. I would like to call this web service once time only.
file.service.ts
getInstrumentBlockDetail(portfolioID, svm) {
var payload = {
"HEADER": this.sh.getHeaderForRequest(),
"CUSTOMER": {
"REFERENCE": portfolioID,
"ID": "",
"INTITULE1": "",
"INTITULE2": "",
"ACCESS": 0,
"SERVICE": 0,
"DEFAULTPTF": 0
},
"SVM": svm
}
return this.http.post < any[] > (this.getBaseUrl() + `/WLOLBLOK`, payload);
}
file.ts
ngOnInit() {
this.svm = this.AR.snapshot.paramMap.get('svm');
this.currentPortfolio = this.shrd.getData('currentPortfolio');
this.pageTitle = "";
this.initiate();
}
getBlocked() {
return this.api.getInstrumentBlockDetail(this.currentPortfolio, this.svm)
.pipe(
map((response: {}) => {
this.prepareDataForBlocked(response);
})
);
}
prepareDataForBlocked(res) {
if (res.RETURNCODE == 'OKK00') {
this.spinners.blockDetails = false;
this.pageTitle = " " + res.BLOCAGES.INFOTITRE.LABEL + " (" + res.BLOCAGES.INFOTITRE.PLACELABEL + ")";
}
}
getBlocage() {
return this.api.getInstrumentBlockDetail(this.currentPortfolio, this.svm)
.pipe(
map((response: {}) => {
this.prepareDataForBlocage(response);
})
);
}
prepareDataForBlocage(response) {
this.spinners.blockDetails = false;
if (response['RETURNCODE'] == "OKK00") {
this.myList = response['BLOCAGES']['BLOCAGE']
.filter(blocage => blocage['QTE'] != 0)
.map(blocage => ({
quantity: blocage['QTE'],
raison: blocage['RAISON_LIB'],
update: blocage['DAT'],
rem1: blocage['REM1'],
rem2: blocage['REM2']
}));
let totalQt = response['BLOCAGES']['QTEBLOQTOT'];
this.statusLine = {
total: totalQt
};
}
}
initiate() {
this.getBlocked().subscribe(res => {
this.spinners.blockDetails = true;
this.getBlocage()
.pipe(
concatMap(res => this.getBlocage()),
).subscribe()
})
}
goBack() {
this.helpers.goBack();
}
How can I solve this problem, please ?
Thank you so much.
Use share observable for RxJs operator.

get element index of an object

i need to get the index of an element in this object (returned as JSON.parse(data)), i tried with findIndex
datosReserva, datosReserva.Reservas and nothing... it says findIndex is not a function.
function checkReserva(){
var options = {
'method': 'GET',
'uri': urlAPI,
'headers': {
'Content-Type': 'application/x-www-form-urlencoded',
}
};
request(options, function (error, response) {
let reserva;
if (error){
throw new Error(error);
}else {
// console.log(response.body);
reserva = response.body;
//console.log(reserva)
}
return checkIndex(reserva, "2929 25-06-2020 10:00");
//"2929 25-06-2020 10:00" for testing
});
}
function checkIndex(datosReserva, reserva) {
const elemento = (element) => element.reserva == reserva;
console.log(datosReserva.findIndex(elemento))
}
{
"Reservas": [
{
"reserva": "2929 22-06-2020 11:20",
"id": "1",
"status": "on"
},
{
"reserva": "2929 25-06-2020 10:00",
"id": "5",
"status": "on"
}
]
}
var Reservas = Json.parse(response.body).Reservas;
return checkIndex(Reservas , "2929 25-06-2020 10:00");
function checkIndex(Reservas, reserva) {
let index = -1;
Reservas.forEach((element, idx)=>{
if(element.reserva == reserva) {
index = idx;
}
});
return index;
}
well i found the solution. I needed to parse the response to object. Thank you everyone!!
function checkIndex(datosReserva, stringReserva){
var reservas = JSON.parse(datosReserva)
const elemento= (element) => element.reserva == stringReserva;
var index = reservas.Reservas.findIndex(elemento);
console.log(reservas.Reservas.findIndex(elemento));
//return index;
}

Add copy to to eslaticsearch on index template

I use elasticsearch 6.2, and I want to optimize the elasticsearch search functionality to copy all field value to one value and generate than searching by query string on one field instead of multiple field. How to do that? How to copy all fields, now matter which to one filed.
initialize index template
export const init = async types => {
try {
let client = createClient()
const templateSettings = {
index_patterns : ['*'],
settings: indexTemplateSettings,
mappings : types.reduce((p, type) => ({
...p,
[type] : {
numeric_detection: true,
_source : {enabled : true},
'properties': {
'searchIndex': {
'type': 'text',
},
'*': {
'type': 'text',
'copy_to': 'searchIndex',
},
},
},
}), {}),
}
await client.indices.putTemplate({
name: 'default',
body: templateSettings,
},(error, response) => {
logger.silly('Pushing of index template completed', response)
})
} catch (e) {
logger.error(e)
}
}
put index
export const push = (message, type) => new Promise(async resolve => {
try {
let client = createClient()
let indexCreationTime = new Date('2016-02-08').toISOString().substring(0, 10)
// '2016-02-08'
console.log(message, 'message')
console.log(type, 'type')
await client.index({
index: type.toLowerCase(),
type,
body: {
...message,
_timestampIndex: indexCreationTime,
},
},
(error, response) => {
logger.silly('Pushing of data completed', response)
resolve(response)
})
} catch (e) {
logger.error(e)
}
})
The best way is to create an index template which leverages a dynamic template that will catch all fields and add the copy_to parameter to their definition.
PUT _template/my-template
{
"index_patterns": ["*"],
"settings": {},
"mappings": {
"_doc": {
"dynamic_templates": [
{
"all": {
"match": "*",
"mapping": {
"type": "text",
"copy_to": "searchIndex"
}
}
}
],
"properties": {
"searchIndex": {
"type": "text"
}
}
}
}
}

How to store callback in node js

function getChild2 (user, userid, level, callback) {
User.find({ 'parentId': new mongoose.Types.ObjectId(userid), 'active': true },
{ "_id": true, "firstName": true,"lastName": true,"userId": true,"rightLeg": true,"leftLeg": true, "userName": true, "children": true, "activePackage": true, "type": true, "styleClass": true, "expanded": true }).
sort({ 'created': -1 }).exec(function (err, users) {
if (err) {
console1.error('Error:User:Read: ' + errorHandler.getErrorMessage(err));
} else {
console1.log('Log:User:Read: user network response ' + JSON.stringify(users));
user.children.push(users);
users.forEach(function (val, i) {
console.log('getchild2 ' + val._id);
getChild2(val, val._id, level+1, null);
});
if (users.length === 0)
{
callback(user);
}
}
});
I need to use the callback when users.length === 0 but on my iteration I am making the callback as null i.e at the end of loop callback is becoming null,then it says the error callback is not a function.Then I thought of storing the callback function initially in a variable.
if (callback !== null) {
toCall = callback;
}
then...
if (users.length === 0 ) {
toCall(users);
}
Now it says toCall is not a function.Can anyone please help me to solve this.Thanks.

How to verify the particular value of the DB node of firebase database

I have a JSON structure as
{
"engagedUsers": {
"qwe": {
"agent_availability": true,
"conv_id": "parthengineer_qwe",
"emailId": "qwe#gmail.com",
"login_time": 1512644440,
"name": "qwe",
"uid": "adasfklsfjdskldgsgjgjkl"
},
"tt": {
"agent_availability": true,
"conv_id": "genesis_tt",
"emailId": "tt#gmail.com",
"login_time": 1512644440,
"name": "tt",
"uid": "adasfklsfjdskldgsgjgjkl"
}
}
}
I want to verify if the conv_id child is equal to parthengineer_qwe. I tried the below code but cannot got through it:
this.engagedRef = firebase.database().ref('engagedUsers');
this.engagedRef.orderByValue().once('value', function (snapshot) {
snapshot.forEach(function (data) {
// console.log("snapShot:" + data.child('conv_id').val());
if ((data.child('conv_id').val() == 'parthengineerqwe') && (existEngageduser !== 1)) {
existEngageduser = 1
// console.log("under haschild:" + existEngageduser);
}
if (existEngageduser == 1) {
isEngaged = true
// sessionStorage.isEngaged = isEngaged;
}
// console.log("isEngaged:" + isEngaged);
})
return isEngaged;
});
Please suggest a better way to achieve this as I know I am not going right way, I expect isEngaged variable as true
I'm still not sure what you want but why not have an external function to do it?
snapshot.forEach(function (data) {
if (isEngaged(data.val())) {
console.log(data.key, ' is engaged');
}
}
function isEngaged(userData) {
return (userData.conv_id === 'parthengineer_qwe') || false;
}

Categories

Resources