Error to emit socket: internal / bootstrap / pre_execution.js: 308 - node.js

internal/bootstrap/pre_execution.js:308
get() {
^
RangeError: Maximum call stack size exceeded
at get (internal/bootstrap/pre_execution.js:308:8)
at hasBinary (/home/spirit/Documents/ProjectsJS/ProjectBack/node_modules/has-binary2/index.js:44:3)
Hello I am trying to issue my socket but I have this error, and I can not receive my socket in the back end below all the code I used
io.on('connection', function (socket) {
setInterval(() => Queue.searching() , 1000);
sessionMap.set(socket.id,socket);
//ADD PLAYER TO QUEUE
socket.on('addPlayer-Queue', (result) => {
const player = {
id:result.id,
socketid: socket.id,
name: result.name,
mmr: result.mmr,
socket: socket
}
const nPlayer = new Player(player);
Queue.addPlayer(nPlayer);
/*
console.log(queue);
console.log(sessionMap.all());*/
//socket.emit('match', matches)
});
});
//
searching = () => {
const firstPlayer = this.getRandomPlayer();
const secondPlayer = this.players.find(
playerTwo =>
playerTwo.mmr < this.calculateLessThanPercentage(firstPlayer) &&
playerTwo.mmr > this.calculateGreaterThanPercentage(firstPlayer) &&
playerTwo.id != firstPlayer.id
);
if(secondPlayer){
const matchedPlayers = [firstPlayer, secondPlayer];
this.removePlayers(matchedPlayers);
Matches.configurePlayersForNewMatch(matchedPlayers);
}
}
//
getMatchConfigurationFor = players => {
console.log(sessionMap.all())
if(players){
const match = new Match(players);
const result = {
idMatch: match.id,
playerOne: match.players[0],
playerTwo:match.players[1]
}
return result;
}
}
configurePlayersForNewMatch = (matchedPlayers) => {
matchedPlayers.forEach(player =>
sessionMap.get(player.socketId)
.broadcast.to(player.socketId)
.emit('match',
this.getMatchConfigurationFor(matchedPlayers)));
}
so what I admit the problem is in this code snippet:
matchedPlayers.forEach(player =>
sessionMap.get(player.socketId)
.broadcast.to(player.socketId)
.emit('match',
this.getMatchConfigurationFor(matchedPlayers)));
The session map is a mapping I made of my sockets saving key (socket id) and socket to send by emit later. on console log about my session.map this is console . log on my socket player https://pastebin.com/XHDXH9ih

Related

Socket connection congests whole nodejs application

I have a socket connection using zmq.js client:
// routerSocket.ts
const zmqRouter = zmq.socket("router");
zmqRouter.bind(`tcp://*:${PORT}`);
zmqRouter.on("message", async (...frames) => {
try {
const { measurementData, measurementHeader } =
await decodeL2Measurement(frames[frames.length - 1]);
addHeaderInfo(measurementHeader);
// Add cell id to the list
process.send(
{ measurementData, measurementHeader, headerInfoArrays },
(e: any) => {
return;
},
);
} catch (e: any) {
return;
}
});
I run this socket connection within a forked process in index.ts:
// index.ts
const zmqProcess = fork("./src/routerSocket");
zmqProcess.on("message", async (data: ZmqMessage) => {
if (data !== undefined) {
const { measurementData, measurementHeader, headerInfoArrays } = data;
headerInfo = headerInfoArrays;
emitHeaderInfo(headerInfoArrays);
// Emit the message to subscribers of the rnti
const a = performance.now();
io.emit(
measurementHeader.nrCellId,
JSON.stringify({ measurementData, measurementHeader }),
);
// Emit the message to the all channel
io.emit("all", JSON.stringify({ measurementData, measurementHeader }));
const b = performance.now();
console.log("time to emit: ", a - b);
}
});
There is data coming in rapidly, about one message per ms, to the zmqRouter object, which it then processes and sends onto the main process where I use socket.io to distribute the data to clients. But as soon as the stream begins, node can't do anything else. Even a setInterval log stops working when the stream begins.
Thank you for your help!

Unexpected behavior in sockets in nodejs (double connections,

PROBLEM:
So I have a reactjs application that I created with npx create-react-app.
I also have a server running on my machine on port 8174(no significance just random). On this server I have some socket.io action going on.
io.on('connection', (socket) => {
console.log('client connected')
}
Something weird which isn't really the problem, but may be related is that when I connect to the server it always runs twice. It will give me the "client connected" output twice in the server console.
The real problem is that I cannot figure out how to get this data into an array on the actual react application.
Here is the code in question:
import React, {useState, useEffect} from 'react'
import socketIOClient from 'socket.io-client'
import TweetCard from './TweetCard'
export default function TweetList() {
const [tweetItems, setTweetItems] = useState([])
const [socket] = useState(() => socketIOClient('http://localhost:8174/', {reconnection: true, forceNew: false}))
var items = []
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
const streamTweets = async () => {
socket.on('tweets', async data => {
await sleep(1000)
items = [...tweetItems, data]
items = items.reverse()
// items = items.filter(d => {return d.user != data.user})
var count = 15
items = items.filter(function(d) {
if(count != 0){
count--
return true
}
return false
})
console.log(items)
setTweetItems(items)
})
}
useEffect(() => {
socket.once('connect', () => {
console.log("Socket has successfully connected to server")
})
streamTweets()
return () => {
socket.on('disconnect', () => {
socket.off("tweets");
socket.removeAllListeners("tweets")
console.log("Socket Disconnected")
})
}
}, [])
return (
<div style={{ height: "300rem", scrollY: "auto", overflowY: "auto"}} >
{tweetItems.map(tweet => {
return <TweetCard tweet={tweet}/>
})}
</div>
)
}
THINGS I'VE TRIED:
On the server level I did a io.once instead of io.on. This fixed the issue of the client connecting twice or a crazy number of times like 5 in one second. It predictively only connected once. The problem with this however is if I refresh the page on the app it disconnects forever and I couldn't figure out how to make it reconnect even though it was saying it was reconnecting. I will post the server code on how it is connecting below, but basically it would output ('resuming stream') when it was infact not resuming the stream.
At first I just messed with the state directly (tweetItems). I basically make an array called newArr = [...tweetItems, data]. Then I set the state below it like setTweetItems(newArr). This however just updated index 0 every single time it set the state. So it would always be an array of one single item. It would update the next tweet though.
Tried using the bearer token instead of using require('twitter') package and tried implementing it in the 'twitter docs way of streaming' I can insert that link if needed. The code is outdated and incorrect though as I came to find out. I literally just forked the entire project at one point and put in my token. It did not work. They also use body parser still so its a strong sign that it is outdated
Tried making a regular array without the state called items =[] this worked for a little bit , and I am not sure what I changed, but it eventually started to copy like 2 or 3 of the same item. like index 0 - 2 would all be the same twee 3 - 4 would all be the same tweet and so on.
Also when I performed a "reverse()" on this items array it would give me a fatal error telling me that items = [...items, data] can't be set. This was odd because the code to reverse items was below this but the error was saying that items can't be set I am assuming it was doing something then after it "reversed" it went to set the items again and was null. I used items = items.reverse() this is what caused the error
Tried making the streaming of the tweets async in the react(did nothing)
Tried slowing down each setState by 1 second(did nothing)
I have tried many more things, but hopefully this will give you an idea of the issue that I am having. Any help or tutorials on sockets would be awesome.
Here is the code that connects to the twitter API:
const Twitter = require('twitter')
module.exports = (app, io) => {
var client = new Twitter({
consumer_key: process.env.CONSUMER_KEY,
consumer_secret: process.env.CONSUMER_SECRET,
access_token_key: process.env.ACCESS_TOKEN_KEY,
access_token_secret: process.env.ACCESS_TOKEN_SECRET
});
let timeout = 0
let socketConnection;
let twitterStream;
app.locals.searchTerm = 'giveaway'
app.locals.showRetweets = false;
//twitter stream
const streamtweets = () => {
console.log("Resuming stream for: " + app.locals.searchTerm)
client.stream('statuses/filter', {track: app.locals.searchTerm, tweet_mode: 'extended', language: 'en'}, (streamData) => {
streamData.on('data', (data) => {
sendMessage(data)
});
streamData.on('error', (error) => {
console.log(error)
})
twitterStream = streamData
})
}
const sleep = async (delay) => {
return new Promise((resolve) => setTimeout(() => resolve(true), delay));
};
//twitter stream
io.on('connection', socket => {
console.log(socket.id)
socketConnection = socket;
streamtweets();
socket.on("connection", () => console.log("Client has connected to the server"))
socket.on("disconnect", () => {
console.log("Client has disconnected to the server")
// twitterStream.destroy()
// socket.off()
// reconnect(twitterStream, socket)
})
})
const reconnect = async (stream, socket) => {
timeout++;
stream.destroy()
await sleep(2 ** timeout * 1000);
// streamTweets(socket, token);
streamtweets()
};
/**
* Sets search term for twitter stream.
*/
app.post('/setSearchTerm', (req, res) => {
let term = req.body.term;
app.locals.searchTerm = term;
twitterStream.destroy();
streamtweets();
});
const sendMessage = (data) => {
if(data.text.includes('RT')){
return;
}
socketConnection.emit("tweets", data)
}
}

Async function inside MQTT message event

I'm using MQTTjs module in a Node app to subscribe to an MQTT broker.
I want, upon receiving new messages, to store them in MongoDB with async functions.
My code is something as:
client.on('message', (topic, payload, packet) => {
(async () => {
await msgMQTT.handleMQTT_messages(topic, payload, process.env.STORAGE,
MongoDBClient)
})
})
But I can't understand why it does not work, i.e. it executes the async function but any MongoDB query returns without being executed. Apparently no error is issued.
What am I missing?
I modified the code in:
client.on('message', (topic, payload, packet) => {
try {
msgMQTT.handleMQTT_messages(topic, payload, process.env.STORAGE,
MongoDBClient, db)
} catch (error) {
console.error(error)
}
})
Where:
exports.handleMQTT_messages = (topic, payload, storageType, mongoClient, db) => {
const dateFormat = 'YYYY-MMM-dddd HH:mm:ss'
// topic is in the form
//
const topics = topic.split('/')
// locations info are at second position after splitting by /
const coord = topics[2].split(",")
// build up station object containing GeoJSON + station name
//`Station_long${coord[0]}_lat${coord[1]}`
const stationObj = getStationLocs(coord.toString())
const msg = JSON.parse(payload)
// what follows report/portici/
const current_topic = topics.slice(2).join()
let data_parsed = null
// parse only messages having a 'd' property
if (msg.hasOwnProperty('d')) {
console.log(`${moment().format(dateFormat)} - ${stationObj.name} (topic:${current_topic})\n `)
data_parsed = parseMessages(msg)
// date rounded down to the nearest hour
// https://stackoverflow.com/questions/17691202/round-up-round-down-a-momentjs-moment-to-nearest-minute
dateISO_String = moment(data_parsed.t).startOf('hour').toISOString();
// remove AQ from station name using regex
let station_number = stationObj.name.match(/[^AQ]/).join('')
let data_to_save = {
id: set_custom_id(stationObj.name, dateISO_String),
//`${station_number}${moment(dateISO_String).format('YMDH')}`,
date: dateISO_String,
station: stationObj,
samples: [data_parsed]
}
switch (storageType) {
case 'lowdb':
update_insertData(db, data_to_save, coll_name)
break;
case 'mongodb': // MongoDB Replicaset
(async () => {
updateIoTBucket(data_to_save, mongoClient, db_name, coll_name)
})()
break;
default: //ndjson format
(async () => {
await fsp.appendFile(process.env.PATH_FILE_NDJSON,
JSON.stringify(data_to_save) + '\n')
})()
//saveToFile(JSON.stringify(data_to_save), process.env.PATH_FILE_NDJSON)
break;
}
// show raw messages (not parsed)
const show_raw = true
const enable_console_log = true
if (msg && enable_console_log) {
if (show_raw) {
console.log('----------RAW data--------------')
console.log(JSON.stringify(msg, null, 2))
console.log('--------------------------------')
}
if (show_raw && data_parsed) {
console.log('----------PARSED data-----------')
console.log(JSON.stringify(data_parsed, null, 2))
console.log('--------------------------------')
}
}
}
}
Only updateIoTBucket(data_to_save, mongoClient, db_name, coll_name) is executed asynchrounsly using mgongodb driver.

Need help on using takeUntil() and Observable.fromEvent() Methods

I'm following this tutorial to create Reactive TCP server in Nodejs
here's code that i've been working on
const Rx = require('rxjs')
const net = require('net')
const uuid = require('uuid');
module.exports = () => {
const sockets = new Map();
const ids = new Map();
const GetSocket = _id => sockets.get(_id);
const GetId = _socket => ids.get(_socket);
const SetSocket = _socket =>{
_socket.setEncoding('utf8');
const _id = uuid();
sockets.set(_id, _socket);
ids.set(_socket,_id);
return _id;
};
const server = net.createServer({ allowHalfOpen: true });
const socketStream = Rx.Observable.fromEvent(server, 'connection');
const RemoveSocket = socket = () => {
console.log("connection closed && removing socket from Map");
const id = ids.get(socket);
sockets.delete(id);
ids.delete(socket)
};
const socketObservable = socket => SetSocket(socket) &&
Rx.Observable
.of({
action: 'CONNECTION',
socket: GetId(socket)
})
.merge(
Rx.Observable
.fromEvent(socket,'data')
.map(d=>{
try {return JSON.parse(d);}
catch (e) {
console.log(e);
return d;
}
})
.map(msg=>{
return Object.assign({action:msg,socket:GetId(socket)})
})
)
.takeUntil(Rx.Observable.fromEvent(socket, 'close').map(d=>{
console.log("!!!! Should remove !!!");
RemoveSocket(socket);
}));
const Print = ()=>{
//ids.forEach(id=> console.log(GetSocket(id)));
console.log("total connected socket : " + ids.size);
};
const startServer = port => server.listen(port) &&
socketStream
.flatMap(socketObservable);
return {startServer, Print , stop: () => server.close()};
};
and here's my test result(just sending test msg and connect/reconnect to server )
{ action: 'CONNECTION',
socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: { test: 1 },
socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: { test: 2 },
socket: '8989b581-dc54-479b-a8c0-870cc8103c5b' }
total connected socket : 1
{ action: 'CONNECTION',
socket: 'b868104b-d1cf-41c9-950f-472f63bac27a' }
total connected socket : 2
{ action: { test: 1 },
socket: 'b868104b-d1cf-41c9-950f-472f63bac27a' }
total connected socket : 2
{ action: 'CONNECTION',
socket: 'b9a579fe-3715-4952-aaf7-d7f64a0bea99' }
total connected socket : 3
Everything working fine till detecting socket close event by TakeUntil()
I tried using takewhile() by simply adding counter like this TakeWhile(cnt < 5)
and socket stream completed as expected.
this is my first attempt to make something with Node.js and feel like i'm missing something.
can anyone help me to understand why takeUntil() is not working here?
Thank you :)
So my confusion was from understanding 'close' and 'end' events
'end' event gets triggered when the client disconnected or server calls socket.end(..) when server receives FIN packet
and 'close' event gets called after socket.destroy()
if anyone wants to see all socket events in action, I recommend watching this video
#Brannon, Thank you for pointing out the right event usage and thank you, everyone, for helping me out with this!!
also just in case, anyone wants working TCP server code.
dependency : rxjs 5.5.0
const Rx = require('rxjs');
const net = require('net');
const uuid = require('uuid');
module.exports = () => {
const sockets = new Map();
const ids = new Map();
const GetSocket = _id => sockets.get(_id);
const GetId = _socket => ids.get(_socket);
const SetSocket = _socket =>{
_socket.setEncoding('utf8');
const _id = uuid();
sockets.set(_id, _socket);
ids.set(_socket,_id);
return _id;
};
const server = net.createServer({ allowHalfOpen: true });
const socketStream = Rx.Observable.fromEvent(server, 'connection');
const RemoveSocket = socket => {
const id = ids.get(socket);
sockets.delete(id);
ids.delete(socket)
console.log("[server.js] socket closed..");
};
const socketObservable = socket => SetSocket(socket) &&
Rx.Observable
.of({
action: 'CONNECTION',
socket: GetId(socket)
})
.merge(
Rx.Observable
.fromEvent(socket,'data')
.map(d=>{
try {return JSON.parse(d);}
catch (e) {
console.log(e);
return d;
}
})
.map(msg=>{
return Object.assign({action:msg,socket:GetId(socket)})
})
)
.takeUntil(Rx.Observable.fromEvent(socket, 'end')
.map(()=>RemoveSocket(socket)));
const Print = ()=>{
//ids.forEach(id=> console.log(GetSocket(id)));
//ids.clear();
console.log("total connected socket : " + ids.size);
};
const startServer = port => server.listen(port) &&
socketStream
.flatMap(socketObservable);
console.log("[server.js] Starts Started" );
return {startServer, Print , stop: () => server.close()};
};

node socket app new instance scope

it is a simple socket app using event base pattern
const invitation = require('./invitation');
module.exports = function(io){
io.on('connection', (socket)=>{
var prepareGame = new PrepareGame(socket)
socket.on("sendInvitation",(data, ack)=>{
prepareGame.sendInvitation(data,ack)
});
});
}
and in prepareGame.js
const events = require('events');
const util = require('util');
class PrepareGame extends events {
constructor(socket) {
super();
this.user = socket.user
var self = this
draftInvitation(data){
this.newInvitation = {
from_user: self.user.id,
to_user: data.to_user,
message:data.message,
created_at:moment().unix(),
}
return this
};
self.on("toSocket", (eventName, clientId, data) => {
console.log(` ===>>>> sending to listener ${eventName}`, clientId);
var client = users[clientId]
if(client)
client.emit(eventName, data)
});
}
// public function
sendInvitation(data, ack) {
// console.log(this);
var self = this
data.message = 'New Invitation'
draftInvitation(data)
.emit("toSocket", "getInvitation", data.to_user, self.newInvitation)
setTimeout(()=>{
data.message = 'Invitation timeout'
draftInvitation(data)
.emit("toSocket", "getInvitation", self.user.id, self.newInvitation)
}, 15000)
if(typeof ack == 'function')
ack({
status:200,
message: "invitation sent",
})
}
}
util.inherits(PrepareGame, events.EventEmitter )
module.exports = PrepareGame
code is sum of different design pattern. it's working fine but I've some queries
io.connection called once to connect to socket and prepareGame
instance created. considering two instance for two user then
how sendInvitation automatically bound correct instance when calling
what happen with new prepareGame instance when socket disconnect ?
i want to remove (data, ack)=>{ } encloser from socket.on mean it
should socket.on ("sendInvitation",prepareGame.sendInvitation) then
how to manage this reference in sendInvitation function

Resources