I reinstalled riak, node.js and riak-js on a new sever (Ubuntu 13.04) and suddenly when I use Riak-JS's db.keys() to get a list of keys in a bucket, it simply never returns.
Here's a test snippet that shows how it fails:
var db = require('riak-js').getClient();
console.log('1');
db.save('bkt','x','1', function(err, data) {
console.log('2');
db.get('bkt','x', function(err, data) {
console.log('3:'+data);
db.keys('bkt', function(err, list) {
console.log('4');
for (key in list) { console.log('5:'+list[key]); }
});
});
});
Here's the output:
1
2
3:1
It doesn't output anything else. I installed the latest Riak (1.4.2), Node.js and Riak-JS (#latest).
Thanks!
According to documentation db.keys() returns event emitter instead of passing the result to the callback. It's because the key list may be very long.
In that case the callback serves only to handle errors.
So instead of passing the callback, you have to use the returned even emitter:
db.keys('bkt', function(err) {
if (err) {
//handle error
}
})
.on('keys', function(list) {
//handle the keys list
//remember, keys may be delivered in batches
})
.on('end', function() {
//handle the end of keys stream
})
.start();
Related
this question is related with an answer to my previous question. there #robertklep recommends me to use mapLimit() instead of .map() because .map() can't handle a large series of data, and with that solution all works fine. But now I restructured my code, and now neither of the .<fn>Limit() functions run after the first loop iteration. do I missing something here?
var proccesBook = function(file, cb) {
testFile(file, function (epub) {
if (epub) {
getEpuData(file, function (data) {
insertBookInDB(data)
})
}else{
cb(file)
}
})
}
async.mapLimit(full_files_path, 10, proccesBook, function(err){
if(err){
console.log('Corrupted file', err);
} else {
console.log('Processing complete');
};
})
// ---> only runs for the first 10 series data
Your primary issue is you don't call cb in the success branch of processBook. Your control flow must guarantee to call the callback exactly once for each worker function invocation.
Other asides:
You don't seem to need the results, so eachLimit is fine
Only need mapLimit if you need the results of each worker
You need to follow the standard error-first convention when calling the callback. Don't do cb(file) as that will be interpretted as an error and about the remaining processing.
var proccesBook = function(file, cb) {
testFile(file, function (epub) {
if (epub) {
getEpuData(file, function (data) {
insertBookInDB(data)
cb() // This is what you were missing
})
}else{
cb()
}
})
}
async.eachlimit(full_files_path, 10, proccesBook, function(err){
if(err){
console.log('Corrupted file', err);
} else {
console.log('Processing complete');
};
})
Executing a find query to my MongoDB DB seems to reset the connection and make the node server crash.
My server handles socket events like this:
io.sockets.on('connection', function(socket) {
MongoClient.connect(url, function(err, db) {
if (err)
console.log('Error');
console.log('Connection established to', url);
var collection = db.collection('spedizioni');
socket.on('adminReq', function() {
handlers.handleAdmin(collection, socket);
});
});
});
the handleAdmin function is:
function handleAdmin(collection, socket) {
console.log('Admin event');
collection.find(null, function(err, raw) {
console.log('Find function');
console.log(raw);
if (err){
socket.emit('err');
console.log('Error function');
}
if (raw) {
socket.emit('adminRes', raw);
console.log('Response function');
} else {
socket.emit('adminNull');
console.log('Null function');
}
});
}
I want the query to return all items on the database; as per the MongoDB manual, I do that by executing a find query without a parameter.
I tried omitting null or using {} as first parameter but nothing changes.
Upon pressing the button to generate the adminReq event, the 'Connection to DB' string is printed on console and the firefox console signals a NEW connection to socket was estabilished; my client script connects at document.load once.
Below is the node console output after that; as you can see the query is executed; looking at the 'raw' output it seems failed attempts were made.
err is null and there is nothing else to output.
Looking at other answers about the 'maximum call stack' exceeded it seems it is caused by a recursive function usually, but it's not the case here.
http://pastebin.com/0xv1qcHn
Why is this the output and not the query result? Why is the connection reset?
A very similar function is working fine and the syntax for returning the whole DB seems correct, feels I am missing something very obvious...
not sure if you should can use null, but i think an empty object should work
you need to convert your result into an array
collection.find({}).toArray(function(err, raw) {
console.log('Find function');
console.log(raw);
if (err){
socket.emit('err');
console.log('Error function');
}
if (raw) {
socket.emit('adminRes', raw);
console.log('Response function');
} else {
socket.emit('adminNull');
console.log('Null function');
}
});
I am learning Node.js; due to asynchronous of Node.js I am facing an issue:
domain.User.find({userName: new RegExp(findtext, 'i')}).sort('-created').skip(skip).limit(limit)
.exec(function(err, result) {
for(var i=0;i<result.length;i++){
console.log("result is ",result[i].id);
var camera=null;
domain.Cameras.count({"userId": result[i].id}, function (err, cameraCount) {
if(result.length-1==i){
configurationHolder.ResponseUtil.responseHandler(res, result, "User List ", false, 200);
}
})
}
})
I want to use result in Cameras callback but it is empty array here, so is there anyway to get it?
And this code is asynchronous, is it possible if we make a complete function synchronous?
#jmingov is right. You should make use of the async module to execute parallel requests to get the counts for each user returned in the User.find query.
Here's a flow for demonstration:
var Async = require('async'); //At the top of your js file.
domain.User.find({userName: new RegExp(findtext, 'i')}).sort('-created').skip(skip).limit(limit)
.exec(function(err, result) {
var cameraCountFunctions = [];
result.forEach(function(user) {
if (user && user.id)
{
console.log("result is ", user.id);
var camera=null; //What is this for?
cameraCountFunctions.push( function(callback) {
domain.Cameras.count({"userId": user.id}, function (err, cameraCount) {
if (err) return callback(err);
callback(null, cameraCount);
});
});
}
})
Async.parallel(cameraCountFunctions, function (err, cameraCounts) {
console.log(err, cameraCounts);
//CameraCounts is an array with the counts for each user.
//Evaluate and return the results here.
});
});
Try to do async programing allways when doing node.js, this is a must. Or youll end with big performance problems.
Check this module: https://github.com/caolan/async it can help.
Here is the trouble in your code:
domain.Cameras.count({
"userId": result[i].id
}, function(err, cameraCount) {
// the fn() used in the callback has 'cameraCount' as argument so
// mongoose will store the results there.
if (cameraCount.length - 1 == i) { // here is the problem
// result isnt there it should be named 'cameraCount'
configurationHolder.ResponseUtil.responseHandler(res, cameraCount, "User List ", false, 200);
}
});
thanks for your help...struggling big time with how to handle this properly. I'm in async now, having given up on my ability to write the callbacks properly. I have snippet where I'm passing a set of random numbers (eachrecord) and passing them through to a mongoose call. Trying to create a data set from the multiple queries I pass.
My issue is that no matter what I've done for 4 hours, the "newarray" variable is always empty.
Thank you for your help -
async.forEach(arLimit, function(eachrecord, callback){
newarray = new Array;
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
console.log(err);
else {
newarray.push(data);
}
});
callback(null, newarray);
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});
There are several issues with your code:
async.forEach isn't meant to 'generate' results, that's what async.map is for;
you need to call the callback only when execFind is done, and not immediately after calling it;
your newarray is probably not necessary;
So try this instead:
async.map(arLimit, function(eachrecord, callback){
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
callback(err); // pass error along
else {
callback(null, [ data ]);
// although I think you mean this (because 'data' is probably an array already)
// callback(null, data);
}
});
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});
I know this will be something small I'm missing, but would appreciate the help.
Here is my test script (node.js)
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/myTestDB',
function (err, db) {
if (err)
debugger;
else {
db.collection('test', function (err, collection) {
collection.save({ name: "danny" }, function () { debugger;});
collection.find(function (err, results) {
if(results.items.length == 0){
///======> always = 0 !!!! WHY?!!!!
debugger;
}
});
});
}
db.close();
});
feel free to start your answer with "duh!"
UPDATE: you also need to move your db.close(); call inside the find callback or you're closing the connection before you're done with it.
In your example, results is a cursor, not an array of docs, so you need to call toArray on it to iterate over the cursor and get the array of docs. But you also need to put your find call inside the save callback. Otherwise the find is executing before the save has completed.
So something like this instead:
collection.save({ name: "danny" }, function () {
collection.find().toArray(function (err, results) {
// results contains the array of docs
// Now you can close the connection.
db.close();
});
});