So I have a app where I loades messages from my Server/Database. Now I have a big problem which is not really great for the users:
--> When I for loop the messages payload from the backend my whole App is hanging and I can't click anywhere else to e.g. go back and so on.
This is my for loop:
const handleMessagesPayload = (messages, new_page_number) => {
if (messages != null && messages != "undefined" && messages != "None"){
setPageNumber(new_page_number)
console.log(messages)
for (var i = 0; i < messages.length; i++) {
appendChatMessage(messages[i], false)
};
}
}
appendChatMessage function:
const appendChatMessage = (data, isNewMessage) => {
var msg = data.message
var timestamp = data.natural_timestamp
var user_id = data.user_id
var username = data.username
var message_id = data.message_id
logData(msg, timestamp, user_id, username, isNewMessage, message_id)
}
//add the new Messages to array
const logData = (msg, timestamp, user_id, message_username, isNewMessage, message_id) => {
const newMessage = {"message": msg, "username": message_username, "timestamp": timestamp, "message_id": message_id}
newChatMessage.push(newMessage) //newChatMessage is the array I was talking about
};
Do you have any useStates()? This might be the problem if you have any of them because they are very slow.
Related
I am testing MySQL Document Store. In order to properly compare with our relational tables, I am attempting to transform our current table into a collection. There approximately 320K records in the table that I wish to export and add to a new collection. I am attempting to use the Connector/Node.js to do this. To avoid blowing it up, I am attempting to add 10K records at a time, but only the first 10K records are inserted. I have confirmed that it is the first 10K records, it is not overwriting each iteration. And those 10K records are correctly structured.
const mysqlx = require('#mysql/xdevapi');
const config = {
password: 'notMyPassword',
user: 'notMyUser',
host: 'notMyHost',
port: 33060,
schema: 'sample'
};
var mySchema;
var myCollection;
var recCollection = [];
mysqlx.getSession(config).then(session => {
mySchema = session.getSchema('sample');
mySchema.dropCollection('sample_test');
mySchema.createCollection('sample_test');
myCollection = mySchema.getCollection('sample_test');
var myTable = mySchema.getTable('sampledata');
return myTable.select('FormDataId','FormId','DateAdded','DateUpdated','Version','JSON').orderBy('FormDataId').execute();
}).then(result => {
console.log('we have a result to analyze...');
var tmp = result.fetchOne();
while(tmp !== null && tmp !== '' && tmp !== undefined){
var r = tmp;
var myRecord = {
'dateAdded': r[2],
'dateUpdated': r[3],
'version': r[4],
'formId': r[1],
'dataId': r[0],
'data': r[5]
};
recCollection.push(myRecord);
if (recCollection.length >= 10000){
console.log('inserting 10000');
try {
myCollection.add(recCollection).execute();
} catch(ex){
console.log('error: ' + ex);
}
recCollection.length = 0;
}
tmp = result.fetchOne();
}
});
It looks like an issue related to how you handle asynchronous execution. The execute() method of a CollectionAdd statement is asynchronous and it returns a Promise.
In a while loop, unless you "await" for the execution to finish, the construct is not able to handle it for you, even though the first call to the asynchronous method always goes through. That's why it only adds the first 10k documents.
You also need to be careful with APIs like createCollection() and dropCollection() because they are also asynchronous and return back a Promise similarly.
Using your own example (without looking into the specifics) it can be something like the following:
const mysqlx = require('#mysql/xdevapi');
const config = {
password: 'notMyPassword',
user: 'notMyUser',
host: 'notMyHost',
port: 33060,
schema: 'sample'
};
// without top-level await
const main = async () => {
const session = await mysqlx.getSession(config);
const mySchema = session.getSchema('sample');
await mySchema.dropCollection('sample_test');
const myCollection = await mySchema.createCollection('sample_test');
const myTable = mySchema.getTable('sampledata');
const result = await myTable.select('FormDataId', 'FormId', 'DateAdded', 'DateUpdated', 'Version', 'JSON')
.orderBy('FormDataId')
.execute();
const tmp = result.fetchOne();
while (tmp !== null && tmp !== '' && tmp !== undefined) {
let r = tmp;
let myRecord = {
'dateAdded': r[2],
'dateUpdated': r[3],
'version': r[4],
'formId': r[1],
'dataId': r[0],
'data': r[5]
};
recCollection.push(myRecord);
if (recCollection.length >= 10000){
console.log('inserting 10000');
try {
await myCollection.add(recCollection).execute();
} catch (ex) {
console.log('error: ' + ex);
}
recCollection.length = 0;
}
tmp = result.fetchOne();
}
}
main();
Disclaimer: I'm the lead developer of the MySQL X DevAPI connector for Node.js
I receive these huge Strings via WebSocket:
[
"BTC-31DEC21-100000-P",
"{\"data\":{\"bids\":{\"0.01\":{\"price\":0.01,\"volume\":66.2,\"exchange\":\"DER\"},\"5.0E-4\":{\"price\":5.0E-4,\"volume\":1.1,\"exchange\":\"DER\"},\"0.637\":{\"price\":0.637,\"volume\":8.4,\"exchange\":\"DER\"}},\"asks\":{\"0.664\":{\"price\":0.664,\"volume\":8.4,\"exchange\":\"DER\"}}},\"isMasterFrame\":true}"
]
or
[
"BTC-31DEC21-36000-C",
"{\"data\":[{\"price\":0.422,\"volume\":8.4,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
]
or
[
"BTC-31DEC21-60000-P",
"{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
]
I want to make JavaScript Buffer where I can store the data and reset it if I receive JSON with isMasterFrame = true
let payload = JSON.parse(messageString[1]);
if (payload.hasOwnProperty("isMasterFrame")) {
for (let i = 0; i < payload.pairs.length; i++) {
let currentPair = payload.data[i]
currentPair = currentPair.replace(/\0/g, ''); //Remove null chars
if (currentPair.toUpperCase() != 'KILL') {
// reset the buffer and start again to fill data
}
}
} else {
// if we receive "isMasterFrame":false just update the data without reset
}
What are the available options to implement this buffer?
I think this is what you are after. It caches the details until it finds isMasterFrame: true && KILL, at which time it clears the cache and starts over again.
EDIT: Stored data using BTC style string as key and data as value to enable querying cache.
let messageCache = {};
const messages = [
["BTC-31DEC21-36000-C", "{\"data\":[{\"price\":0.422,\"volume\":8.4,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"],
["BTC-31DEC21-36000-D", "{\"data\":[{\"price\":0.422,\"volume\":8.4,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"],
["BTC-31DEC21-60000-P", "{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"KILL\"}],\"isMasterFrame\"\:true}"],
["BTC-31DEC21-60000-Q", "{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\"\:false}"]
];
function processData(key, payload) {
if (!payload.isMasterFrame) {
messageCache[key] = payload;
return;
}
for (let obj of payload.data) {
Object.values(obj).forEach(item => {
item = item.toString().replace(/\0/g, ''); //Remove null chars
if (item.toUpperCase() !== 'KILL') {
messageCache = {}; // Clear the cache/buffer
}
});
}
}
function queryCache(key){
return messageCache[key];
}
messages.forEach(message => {
const payload = JSON.parse(message[1]);
processData(message[0], payload);
console.log("Number of cached messages: " + Object.keys(messageCache).length);
});
console.log('Query Cache [BTC-31DEC21-60000-Q]:');
let result = queryCache('BTC-31DEC21-60000-Q');
console.log(result);
I tried to send my variable back from foreground.js to background.js by using an unchanged variable, and it works. Now I can't send some data that I use my AddEventListener syntax to store the data into the variable to call its back to background.js here are my code on foreground.js
foreground.js
console.log("foreground.js injected");
var pswdBtns = [];
let hrefLists = [];
var data = {};
var i;
function readUUID(){
var navigator_info = window.navigator;
var screen_info = window.screen;
var uid = navigator_info.mimeTypes.length;
uid += navigator_info.userAgent.replace(/\D+/g, '');
uid += navigator_info.plugins.length;
uid += screen_info.height || '';
uid += screen_info.width || '';
uid += screen_info.pixelDepth || '';
return uid;
}
async function passwordProtected(pointerList){
const date = new Date();
const uid = readUUID();
alert("You are in dangerous on \'"+ pointerList.title + "\' row = " + pointerList.id.slice(20));
data = {
"Webtitle": pointerList.href,
"Title": pointerList.title,
"Time": date.toString(),
"UUID": uid
}
console.log("foreground = ", data);
return data;
}
console.log("Start loop")
//This function made for collect each id in passwordShowPasswordButton
for(i = 0; i<=pswdBtns.length; i++){
if(document.querySelector("#passwordShowPasswordButton_"+ i) == null){
console.log("This is your limit!!");
}
else{
hrefLists[i] = document.querySelector("#passwordWebsitelink_"+ i);
pswdBtns[i] = document.querySelector("#passwordShowPasswordButton_"+ i);;
data = pswdBtns[i].addEventListener('click', passwordProtected.bind(pswdBtns[i], hrefLists[i]));
console.log(hrefLists[i].title); /* Title VARCHAR(30) */
console.log(hrefLists[i].href); /* Website VARCHAR(50) */
}
}
console.log("End");
and these are my code on background.js
background.js
const edgePswd = "edge://settings/passwords";
const settingPage = "edge://settings/";
chrome.tabs.onActivated.addListener(async (tab) => {
await chrome.tabs.get(tab.tabId, (current_tab_info) => {
var pswdPageChecked = 1;
while(pswdPageChecked < 2) {
if (edgePswd == current_tab_info.url) {
chrome.tabs.executeScript(null, { file: "/extension/foreground.js" }, (data) => {
console.log("Coming to foreground");
console.log(data);
});
pswdPageChecked++;
}
}
});
});
It would be a pleasure if someone can figure this.
ïm trying to send a notifications to all the users that a device have in firebase database, but it says: "ReferenceError: value is not defined" in the register of the cloud function.
What is supposed to do is: every time a change is made in "Notifications", you must obtain the data that was changed, with this data look in the device table and send a notification to all the tokens that are in that device.
This is the error:
Code of the cloudfunction:
const functions = require('firebase-functions');
const admin = require('firebase-admin'); // this is the Admin SDK, not firebase-functions
admin.initializeApp(functions.config().firebase);
const db = admin.database()
const ms = admin.messaging()
exports.notifications = functions.database.ref('Notifications/{id}').onUpdate(async(evt) =>{
const payload = {
notification:{
title : 'Alarma se activó tu cerca',
body : 'Se activó tu cerca, revisala',
badge : '1',
sound :'defaul'
}
};
//Get Notification Device ID
const notySnap = await db.ref('Notification/').once('value');
var devicee = notySnap.notty;
var dev = JSON.stringify(devicee);
//Get number of users that the device had
const usersSnap = await db.ref('Devices/'+ dev + '/Users').once(value)
const nUsers = usersSnap.nUsers;
var Nusers = JSON.stringify(nUsers);
var nNUsers = parseInt(Nusers);
//Send notification to the number of users that exist
if (Nusers !== null){
for(i = 1; 1 <=nNUsers; i++){
if(i === 1){
const userToSendP1 = usersSnap.user1;
var userToSend1 = JSON.stringify(userToSendP1);
Console.log("Mensaje enviado a user 1");
return ms.sendToDevice(userToSend1, payload);
}else if(i === 2){
const userToSendP2 = usersSnap.user2;
var userToSend2 = JSON.stringify(userToSendP2);
Console.log("Mensaje enviado a user 2");
return ms.sendToDevice(userToSend2, payload);
}else if(i === 2){
const userToSendP3 = usersSnap.user3;
var userToSend3 = JSON.stringify(userToSendP3);
Console.log("Mensaje enviado a user 3");
return ms.sendToDevice(userToSend3, payload);
}else if(i === 2){
const userToSendP4 = usersSnap.user4;
var userToSend4 = JSON.stringify(userToSendP4);
Console.log("Mensaje enviado a user 4");
return ms.sendToDevice(userToSend4, payload);
}
}
}
return null
})
DataBase:
In this line:
const usersSnap = await db.ref('Devices/'+ dev + '/Users').once(value)
value is a variable that you never defined. That's what the error message means. You probably meant this instead, with 'value' as a string:
const usersSnap = await db.ref('Devices/'+ dev + '/Users').once('value')
I want to create a multi user login system with private messages.
I created the theory in JavaScript (just for sketching out the theory and functionalities), and I wonder if I am on the right track.
Of course I will change it to a backend language later on with all the validations, this is purely for sketching.
// User database simulation
var users = [];
var defaultUser = {
'rights': 1, /* 0 - 3: 0 is banned, 1 is default, 2 is moderator, 3 is admin */
'activated': false,
'createdAt': null,
'updatedAt': null,
'username': null,
'userId': null,
'email': null,
'pass': null, /* will be encrypted */
'profile': {
'sex': null,
'age': null,
'avatar': null,
'updatedAt': null,
},
'messages': {
'inbox': [],
'outbox': [],
'trash': [],
'drafts': []
}
};
var defaultMessage = {
'id': null,
'date': null,
'from': null,
'to': null,
'message': null
};
var userManagement = {
'register': function(username, email, pass){
var user = $.extend({}, defaultUser);
user.username = username;
user.email = email;
user.pass = pass;
user.userId = username + '_' + Math.floor(Date.now() / 1000);
// If everything is valid, register:
// User database insert simulation
users.push(user);
console.log('Registered', user);
},
'login': function(username, pass) {
// User database query simulation
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.username === username) {
if(user.pass === pass) {
console.log('Logged in', user);
} else {
console.log('Pass incorrect');
}
} else {
console.log('User not found');
}
}
},
'forgotUsername': function(email) {
// User database query simulation
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.email === email) {
console.log('username ['+ user.username +'] send to ' + user.email);
} else {
console.log('User not found');
}
}
},
'forgotPass': function(username) {
// User database query simulation
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.username === username) {
console.log('pass from user ['+ user.username +'] send to ' + user.email);
} else {
console.log('User not found');
}
}
},
'getUserById': function(userId){
var key;
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.userId === userId) {
return user;
}
}
return null;
},
'getUserByUsername': function(username){
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.username === username) {
return user;
}
}
return null;
}
/* TODO: updateProfile, activate */
}
var message = {
'send': function(fromUserId, toUserId, msg){
var sender = userManagement.getUserById(fromUserId);
var receiver = userManagement.getUserById(toUserId);
var message = $.extend({}, defaultMessage);
message.id = fromUserId + '_' + Math.floor(Date.now() / 1000);
message.from = sender.username;
message.fromUserId = fromUserId;
message.to = receiver.username
message.toUserId = toUserId;
message.message = msg;
message.date = new Date();
sender.messages.outbox.push(message);
receiver.messages.inbox.push(message);
}
/* TODO: delete, move etc. */
}
userManagement.register('barry', 'barry#test.nl', 'bcf2ibc');
userManagement.register('john', 'john#test.nl', 'bahjscb');
userManagement.login('test', 'blabla'); // fail
userManagement.login('barry', 'blabla'); // fail
userManagement.login('barry', 'bcf2ibc'); // success
userManagement.login('John', 'bahjscb'); // success
//userManagement.forgotPass('barry');
var barry = userManagement.getUserByUsername('barry');
var john = userManagement.getUserByUsername('John');
message.send(barry.userId, john.userId, 'My test message.');
message.send(barry.userId, john.userId, 'You received my previous message?');
message.send(john.userId, barry.userId, 'Yes I did received them.');
console.log(users);
JS Fiddle: https://jsfiddle.net/vmjs1n9n/12/
They way I setup the private message per user, is that a good thing to do? I would appreciate advice on the rest as well!
It's a start, if your primary intent is to facilitate private messages, then yes, private message per user is a good thing to do.
My first thoughts, you know you are re-inventing the wheel right? If I was given this as a business requirement I would integrate with an existing messaging service or protocol rather than have to deal with the long term management of this kind of data. Even authentication, in this day you should be attempting to implement some kind of open authentication standard, like OAuth, again to reduce the amount effort you need to spend to get this off the ground and keep it running long term.
I normally wouldn't put message data physically into the sender's outbox and then into the receivers inbox as well, primarily because your data storage would be double, but I guess like email, routing copies of the original message would make management of the messages really simple, whilst making it hard to accidentally give one user access to another's messages.
Here because you are prototyping, it's hard to provide decent comments because you have already alluded to the fact that you will do things differently in the backend so I don't want to second guess where you have already decided to go with this. For a simple system like this the UI should be really lite, with the logic in the backend, the specific logic is where I would like to provide future comments and insights.