How to change the id of a socket? - node.js

I'm making an app in node.js and I noticed that every time users open a new page or change page they get a different socket id. It is possible to change the id of that socket so the user has always the same socket id?
When the user connects to the server, it saves the uid and the id of the socket in mongodb and get that data each time he connects.
This is my code:
nspm.on('connection', function(socket) {
db.c_oneusr(socket.decoded_token, function(err, docs){
if(docs) {
if(docs.ban=='1') {
nspm.to(socket.id).emit('ckusr', 'banned');
socket.disconnect();
return;
}
else {
nspm.to(socket.id).emit('ckusr', 'ok');
if (!docs.laston) {
docs.laston = 0;
}
initializeConnection(socket, docs.laston);
}
}
else {
nspm.to(socket.id).emit('ckusr', 'ok');
initializeConnection(socket, 0);
}
});
});
function initializeConnection(socket, laston){
var online = [];
laston = new Date(laston);
socket.uid = socket.decoded_token.uid;
socket.buddies = socket.decoded_token.buddies;
// id contains all ids of each user
if (!id[socket.uid]) {
id[socket.uid] = {};
}
id[socket.uid][socket.id] = 1;
socket.join(socket.uid);
for (var buddy in socket.buddies) {
var buddy_id = socket.buddies[buddy];
socket.join(buddy_id);
if (uidlist[buddy_id]) {
online.push(parseInt(buddy_id, 10));
}
}
socket.emit('login', {
online: online
});
socket.broadcast.to(socket.uid).emit('user joined', {
uid: socket.uid
});
data = [];
data["uid"] = socket.decoded_token.uid;
data["id"] = socket.id;
db.updpml(data); // Update user data
}

Related

How to connect my electron app using PouchDB (leveldb) with Cloudant or any other database that support couchDB and sync

I'm creating an electron app using pouchDB and I want the app to be able to diferents customers and sync the data between them. As an example I'm making the tutorial: https://github.com/nolanlawson/pouchdb-getting-started-todo, I adapt the code to electron and I created a noSQL database at cloudant.
At the moment I can save data but I cannot sync with my remote db that is in cloudant. Here is the endpoint I'm using to sync data between both database.
Here is the error that I'm getting.
Here is the code of my script.js
(function() {
'use strict';
var $ = document.querySelector.bind(document);
var ENTER_KEY = 13;
var newTodoDom = document.getElementById('new_todo');
var syncDom = document.getElementById('sync-wrapper');
// EDITING STARTS HERE (you dont need to edit anything above this line)
var NodePouchDB = require('pouchdb');
var db = new NodePouchDB('todos');
var couchdb = require('felix-couchdb')
var remoteCouch = couchdb.createClient(5984, 'https://ac725f4e-29ec-4614-8e96-02ebc74a529b-bluemix.cloudant.com/')
db.info(function(err, info) {
console.log("is working", info)
db.changes({
since: info.update_seq,
live: true
}).on('change', showTodos);
});
// We have to create a new todo document and enter it in the database
function addTodo(text) {
var todo = {
_id: new Date().toISOString(),
title: text,
completed: false
};
db.put(todo).then(function (result) {
console.log("everything is A-OK");
console.log(result);
}).catch(function (err) {
console.log('everything is terrible');
console.log(err);
});
}
// Show the current list of todos by reading them from the database
function showTodos() {
db.allDocs({include_docs: true, descending: true}).then(function(doc) {
redrawTodosUI(doc.rows);
}).catch(function (err) {
console.log(err);
});
}
function checkboxChanged(todo, event) {
todo.completed = event.target.checked;
console.log(todo);
db.put(todo);
}
// User pressed the delete button for a todo, delete it
function deleteButtonPressed(todo) {
db.remove(todo);
}
// The input box when editing a todo has blurred, we should save
// the new title or delete the todo if the title is empty
function todoBlurred(todo, event) {
var trimmedText = event.target.value.trim();
if (!trimmedText) {
db.remove(todo);
} else {
todo.title = trimmedText;
db.put(todo);
}
}
// Initialise a sync with the remote server
function sync() {
syncDom.setAttribute('data-sync-state', 'syncing');
var opts = {live: true};
db.sync(remoteCouch, opts, syncError);
}
// EDITING STARTS HERE (you dont need to edit anything below this line)
// There was some form or error syncing
function syncError() {
syncDom.setAttribute('data-sync-state', 'error');
}
// User has double clicked a todo, display an input so they can edit the title
function todoDblClicked(todo) {
var div = document.getElementById('li_' + todo._id);
var inputEditTodo = document.getElementById('input_' + todo._id);
div.className = 'editing';
inputEditTodo.focus();
}
// If they press enter while editing an entry, blur it to trigger save
// (or delete)
function todoKeyPressed(todo, event) {
if (event.keyCode === ENTER_KEY) {
var inputEditTodo = document.getElementById('input_' + todo._id);
inputEditTodo.blur();
}
}
// Given an object representing a todo, this will create a list item
// to display it.
function createTodoListItem(todo) {
var checkbox = document.createElement('input');
checkbox.className = 'toggle';
checkbox.type = 'checkbox';
checkbox.addEventListener('change', checkboxChanged.bind(this, todo));
var label = document.createElement('label');
label.appendChild( document.createTextNode(todo.title));
label.addEventListener('dblclick', todoDblClicked.bind(this, todo));
var deleteLink = document.createElement('button');
deleteLink.className = 'destroy';
deleteLink.addEventListener( 'click', deleteButtonPressed.bind(this, todo));
var divDisplay = document.createElement('div');
divDisplay.className = 'view';
divDisplay.appendChild(checkbox);
divDisplay.appendChild(label);
divDisplay.appendChild(deleteLink);
var inputEditTodo = document.createElement('input');
inputEditTodo.id = 'input_' + todo._id;
inputEditTodo.className = 'edit';
inputEditTodo.value = todo.title;
inputEditTodo.addEventListener('keypress', todoKeyPressed.bind(this, todo));
inputEditTodo.addEventListener('blur', todoBlurred.bind(this, todo));
var li = document.createElement('li');
li.id = 'li_' + todo._id;
li.appendChild(divDisplay);
li.appendChild(inputEditTodo);
if (todo.completed) {
li.className += 'complete';
checkbox.checked = true;
}
return li;
}
function redrawTodosUI(todos) {
var ul = document.getElementById('todo-list');
ul.innerHTML = '';
todos.forEach(function(todo) {
ul.appendChild(createTodoListItem(todo.doc));
});
}
function newTodoKeyPressHandler( event ) {
if (event.keyCode === ENTER_KEY) {
addTodo(newTodoDom.value);
newTodoDom.value = '';
}
}
function addEventListeners() {
newTodoDom.addEventListener('keypress', newTodoKeyPressHandler, false);
}
addEventListeners();
showTodos();
if (remoteCouch) {
sync();
}
})();
To get to where the problem sits, can you verify that you can speak to the Cloudant database normally, that is using curl from the command-line? Using curl, fetch a document by its _id, perhaps a document you created manually using the Cloudant dashboard. That should shake out any problems with authentication: I note you're using IAM, which isn't always straight-forward -- and to my knowledge, not supported by PouchDB (or wasn't, last time I looked).
If that is the problem, create a new Cloudant instance with IAM+Legacy credentials.

How to connect Javascript to a remote IBM MQ?

I'm making APIs with LoopBack( a Javascript Framework), pushing and getting messages with IBM MQ.
I followed this tut: Nodejs and MQ
I can do it with local Queue Manager, but I dont know how to connect to a remote Queue Manager.
So, can any one explain me how to do this ?
Tks all.
I can do it with that link, which from #JoshMc's comment.
This is my code, it works fine:
module.exports = function (server) {
var mq = require('ibmmq');
var MQC = mq.MQC; // Want to refer to this export directly for simplicity
// The queue manager and queue to be used. These can be overridden on command line.
var qMgr = "QM1";
var qName = "soa.log";
var mqmd = new mq.MQMD(); // Defaults are fine.
var pmo = new mq.MQPMO();
var cd = new mq.MQCD();
var cno = new mq.MQCNO();
cd.ConnectionName = "localhost(1414)";
cd.ChannelName = "CHAN1";
var csp = new mq.MQCSP();
cno.ClientConn = cd;
cno.Options = MQC.MQCNO_CLIENT_BINDING; // use MQCNO_CLIENT_BINDING to connect as client
function putMessage(hObj) {
var msg = Buffer.from(JSON.stringify(coff));
// Describe how the Put should behave
pmo.Options = MQC.MQPMO_NO_SYNCPOINT |
MQC.MQPMO_NEW_MSG_ID |
MQC.MQPMO_NEW_CORREL_ID;
mq.Put(hObj,mqmd,pmo,msg,function(err) {
if (err) {
console.log(formatErr(err));
} else {
console.log("MQPUT successful");
}
});
}
mq.Connx(qMgr, cno, function (err, hConn) {
if (err) {
console.log((err));
} else {
console.log("MQCONN to %s successful ", qMgr);
// Define what we want to open, and how we want to open it.
var od = new mq.MQOD();
od.ObjectName = qName;
od.ObjectType = MQC.MQOT_Q;
var openOptions = MQC.MQOO_OUTPUT;
mq.Open(hConn, od, openOptions, function (err, hObj) {
if (err) {
console.log(formatErr(err));
} else {
console.log("MQOPEN of %s successful", qName);
putMessage(hObj);
}
// cleanup(hConn, hObj);
});
}
});
};

Transform publish MeteorJS with count of show

I try to use limit : count with transform observer in Meteor and don't understand how to do it without "dirty" solutions.
Code I have on Client (not all, but main part)
var self = this;
self.autorun(function() {
self.subscribe('posts', Session.get('count')); // some Number like 10
}); // client
And on server where I try to use it
Meteor.publish('posts', function(count){
check(count, Number);
let i = 0;
var transform = function(doc) {
console.log(i,count);
if (i < count){ // I try something here
doc.description = new Date();
i++;
return doc;
}
else self.ready();
}
var self = this;
var observer = Posts.find().observe({
added: function (document) {
self.added('posts', document._id, transform(document));
},
changed: function (newDocument, oldDocument) {
self.changed('posts', document._id, transform(newDocument));
},
removed: function (oldDocument) {
self.removed('posts', oldDocument._id);
}
});
self.onStop(function () {
observer.stop();
});
self.ready();
});
Any idea how to limit count of shown documents with transform in publish ?
Just use Posts.find({},{limit:count}) in your query.

How to perform mass inserts into mongodb using NodeJS

I Have to Insert about 10,00000 documents in mongodb using nodejs.
I'm generating these documents using a for loop storing them into an array before finally inserting them into mongodb.
var codeArray = new Array();
for (var i = 0; i<1000000; i++){
var token = strNpm.generate();
var now = moment().format('YYYYMMDD hhmmss');
var doc1 = {id:token,
Discount_strId:"pending",
Promotion_strCode:token,
Promotion_strStatus:"I",
Promotion_dtmGeneratedDate:now,
User_strLogin:"test",
Promotion_strMode:"S",
Promotion_dtmValidFrom:"pending",
Promotion_dtmValidTill:"pending",
LastModified_dtmStamp:now
};
codeArray.push(doc1);
db.collection('ClPromoCodeMaster').insert(codeArray, function (err, result) {
if (err){
console.log(err);
}else{
console.log('Inserted Records - ', result.ops.length);
}
});
The problem I'm facing is mongo has an inserting limit of 16mb, so I can't insert the entire array at once.
Please suggest most optimum solutions.
The main problem is in the request size and not the document size, but it amounts to the same limitation. Bulk operations and the async library with async.whilst will handle this:
var bulk = db.collection('ClPromoCodeMaster').initializeOrderedBulkOp(),
i = 0;
async.whilst(
function() { return i < 1000000; },
function(callback) {
var token = strNpm.generate();
var now = moment().format('YYYYMMDD hhmmss');
var doc = {
id:token,
Discount_strId:"pending",
Promotion_strCode:token,
Promotion_strStatus:"I",
Promotion_dtmGeneratedDate:now,
User_strLogin:"test",
Promotion_strMode:"S",
Promotion_dtmValidFrom:"pending",
Promotion_dtmValidTill:"pending",
LastModified_dtmStamp:now
};
bulk.insert(doc);
i++;
// Drain every 1000
if ( i % 1000 == 0 ) {
bulk.execute(function(err,response){
bulk = db.collection('ClPromoCodeMaster').initializeOrderedBulkOp();
callback(err);
});
} else {
callback();
}
},
function(err) {
if (err) throw err;
console.log("done");
}
);
I should note that regardless there is an internal limit on bulk operations to 1000 operations per batch. You can submit in larger sizes, but the driver is just going to break these up and still submit in batches of 1000.
The 1000 is a good number to stay at though, since it is already in line with how the request will be handled, as well as being a reasonable number of things to hold in memory before draining the request queue and sending to the server.
For inserting millions of record at a time, Create node.js child process fork with MongoDb bulk api.
Child Process Creation:(index.js)
const {fork} = require("child_process");
let counter = 1;
function createProcess(data){
const worker = fork("./dbOperation");
worker.send(data);
worker.on("message", (msg) => {
console.log("Worker Message :",counter, msg);
counter++;
})
}
function bulkSaveUser(records) {
const singleBatchCount = 10000; // Save 10,000 records per hit
const noOfProcess = Math.ceil(records/singleBatchCount);
let data = {};
console.log("No of Process :", noOfProcess);
for(let index = 1; index <= noOfProcess; index++) {
data.startCount = (index == 1) ? index : (((index - 1) * singleBatchCount) + 1);
data.endCount = index * singleBatchCount;
createProcess(data);
}
}
bulkSaveUser(1500000);
DB Operation (dbOperation.js)
const MongoClient = require('mongodb').MongoClient;
// Collection Name
const collectionName = "";
// DB Connection String
const connString = "";
process.on("message", (msg) => {
console.log("Initialize Child Process", msg)
const {startCount, endCount} = msg;
inputStudents(startCount, endCount);
});
function initConnection() {
return new Promise(function(r, e) {
MongoClient.connect(connString, function(err, db) {
if (err) e(err)
r(db);
});
});
}
function inputStudents(startCount, endCount) {
let bulkData = [];
for(let index = startCount; index <= endCount; index++ ){
var types = ['exam', 'quiz', 'homework', 'homework'];
let scores = []
// and each class has 4 grades
for (j = 0; j < 4; j++) {
scores.push({'type':types[j],'score':Math.random()*100});
}
// there are 500 different classes that they can take
class_id = Math.floor(Math.random()*501); // get a class id between 0 and 500
record = {'student_id':index, 'scores':scores, 'class_id':class_id};
bulkData.push({ insertOne : { "document" : record } })
}
initConnection()
.then((db) => {
const studentDb = db.db("student");
const collection = studentDb.collection(colName)
console.log("Bulk Data :", bulkData.length);
collection.bulkWrite(bulkData, function(err, res) {
if (err) throw err;
//console.log("Connected Successfully",res);
process.send("Saved Successfully");
db.close();
});
})
.catch((err) => { console.log("Err :", err) });
}
Sample project to insert millions of record in mongodb using child process fork

Refresh the content without page refresh

hello i have developed the chat application using socket.io, expressjs and mongoose it works fine. it refreshes after some seconds and fetches new clients from db if exist. problem is that user can feel that div is refreshsing.and also some time take soem time in response. how to avoid this case. here is my code
This is my server side code
setInterval(function () {
var allOnLine;
allOnLine = io.sockets.clients();
for (var client in allOnLine) {
if (allOnLine[client].username == "undefined") {
continue;
} else {
notifyAll(allOnLine[client].username);
}
}
}, 50000);
and here is notify all method
function notifyAll(userName) {
contactModel.find({'userId':userName}, (function (err, contactModel) {
usernames = [];
var contacts = contactModel;
for (var a = 0; a < contacts.length; a++) {
usernames[a] = contacts[a].contactId;
}
var allOnLine;
allOnLine = io.sockets.clients();
for (var client in allOnLine) {
if (allOnLine[client].username == "undefined") {
continue;
} else {
for (var i = 0; i < usernames.length; i++) {
if (allOnLine[client].username == usernames[i]) {
usernames[i] = usernames[i] + " -On";
}
allOnLine[client].username);
}
}
}
io.sockets.to(userName).emit('updateusers', usernames);
}));
}
This is my client code
socket.on('updateusers', function(usernames) {
jQuery('#usernames').html('');
jQuery.each(usernames, function(key, value) {
jQuery('#usernames').append('<div class="chatContact" id="chatLink" onclick="privateChat(\''+value+'\')">' );
}}
any help i had also posted this question but no answer
Your problem is that youdelete everything from usernames and after that you write all contacts. You would better remove the offline contacts from the $('#usernames') and after that to add to that list the online contacts. I writed some functions to show you the functionality. I created html list of online contacts and I also created an array of new online contacts. Here is the code:
<div id="u">
<div class="d" onclick="chat('asd1')">asd1</div>
<div class="d" onclick="chat('asd12')">asd12</div>
<div class="d" onclick="chat('asd13')">asd13</div>
<div class="d" onclick="chat('asd142')">asd14</div>
</div>
Here you have the javascript that you need to run after the DOM is ready:
var onlineUsernames = ["asd211","asd12","asd13","asd14"];
var usernamesContainerID = 'u';
var $usernamesContainer = $('#'+usernamesContainerID);
function extractUsernameFromAttr(onclickValue)
{
return onclickValue.split("'")[1];
}
function buildExistingUsernames($userDivs)
{
var existingUsernames = [];
$userDivs.each(function(index,value){
var username = extractUsernameFromAttr($userDivs[index].getAttribute('onclick'));
existingUsernames.push(username);
})
return existingUsernames;
}
function removeUserFromList($user)
{
document.getElementById(usernamesContainerID).removeChild($user);
}
function addUserToList(value)
{
$('<div/>',{
onclick:"chat('"+value+"')",
class :'d',
text:value
}).appendTo($usernamesContainer);
}
function deleteOfflineContacts(existingUsernames,usernames,$userDivs)
{
$.each(existingUsernames,function(index,value)
{
if($.inArray(value,usernames)==-1)
{
removeUserFromList($userDivs[index]);
}
})
}
function addOnlineContacts(existingUsernames,usernames)
{
$.each(usernames,function(index,value)
{
if($.inArray(value,existingUsernames)==-1)
{
addUserToList(value);
}
})
}
function update($userDivs)
{
var existingUsernames = buildExistingUsernames($userDivs);
deleteOfflineContacts(existingUsernames,onlineUsernames,$userDivs);
addOnlineContacts(existingUsernames,onlineUsernames);
}
var $userDivs = $usernamesContainer.children("div");
setTimeout(function()
{
update($userDivs);
},3000);
If you need it here is a working example: http://jsfiddle.net/9gRyQ/2/

Resources