I'm trying to close my connection after the queue hasn't been active for 5 minutes. I have:
ch.consume(receivingQueue, async function (msg) {
if (msg !== null) {
console.log(msg.content.toString()));
}
});
I read about Channel.cancel() but i'm just not quite sure where to insert that into the flow here since the process is just sitting and waiting for a new message, and I'm not sure where to get the consumerTag as it is not in the msg variable.
I have not tested this, but logic is as follows. setTimeout is set to close connection after 5 mins on every message. If a new message arrives the old timer is cleared by the new message and a new timer is recreated. otherwise the connection closes after 5 mins
const closeConnection = function () {
ch.close()
}
let timer = setTimeout(()=>{}, 0); //initial timer for cleartimeout Maybe refactor this?
ch.consume(receivingQueue, async function (msg) {
clearTimeout(timer);
timer = setTimeout(closeConnection, 300000)
if (msg !== null) {
console.log(msg.content.toString()));
}
});
Related
I am new in this world and I am trying things.
I was trying to build a timer bot... And now I have a little problem, I would like to stop my timer whenever I want.
bot.on('message', message => {
let timer = setInterval(() => {
if (message.content.startsWith('!start'))
message.channel.send("I print something");
}, 10 * 1000)
if (message.content.startsWith('!stop')) {
message.channel.send("Interaval Cleared");
clearInterval(timer);
}})
When I type !stop in my discord channel, it displays me the message but it doesn't stop my timer... I tried with a return; but it didn't work.
Could you help me please ?
Thanks,
Have a good day !
You're starting a new interval each time you run the function. Also, your timer value is scoped to each function call, and not "shared" between calls, you need to make it available between them. The behavior you want should look something like this instead:
bot = {}
bot.timer = 0; // ensures clearInterval doesn't throw an error if bot.timer hasn't been set
bot.listen = message =>{
if(message == 'start'){
clearInterval(bot.timer); // stops the interval if it been previously started
bot.timer = setInterval(()=>console.log('I print something'),1000)
}
if(message == 'stop') clearInterval(bot.timer);
}
My app is a game where a user has 30 mins to finish....node backend
Each time a user starts a game then a setInterval function is triggered server side....once 30mins is counted down then I clearInterval.
How do I make sure that each setInterval is unique to the particular user and the setInterval variable is not overwritten each time a new user starts a game? (or all setInterval's are cleared each time I clear).
Seems like I might need to create a unique "interval" variable for each new user that starts game??
Below code is triggered each time a new user starts a game
let secondsLeft = 300000;
let interval = setInterval(() => {
secondsLeft -= 1000;
if (secondsLeft === 0) {
console.log("now exit");
clearInterval(interval);
}
}, 10000);
Thanks!!
We used agenda for a pretty big strategy game backend which offers the benefit of persistence if the node app crashes etc.
We incorporated the user id into the job name and would then schedule the job, along with data to process, to run at a determined time specifying a handler to execute.
The handler would then run the job and perform the relevant tasks.
// create a unique jobname
const jobName = `${player.id}|${constants.events.game.createBuilding}`;
// define a job to run with handler
services.scheduler.define(jobName, checkCreateBuildingComplete);
// schedule it to run and pass the data
services.scheduler.schedule(at.toISOString(), jobName, {
id: id,
instance: instance,
started: when
});
Worked pretty well and offered decent protection against crashes. Maybe worth considering.
First: Concurrent Intervals and Timers are not the best design approach in JS, it is better to use one global timer and a list of objects storing the start, end, userid etc and update these in a loop.
Anyway. To have your interval id bound to a certain scope, you can use a Promise like so:
const createTimer = (duration, userid) => new Promise(res => {
const start = new Date().getTime();
let iid;
(function loop () {
const
now = new Date().getTime(),
delta = now - start
;
//elapsed
if (delta >= duration) {
clearTimeout(iid);
res(userid);
//try again later
} else {
iid = setTimeout(loop, 100)
}
})();
});
This way each timer will run »on its own«. I used setTimeout here since that wont requeue loop before it did everything it had to. It should work with setInterval as well and look like that:
const runTimer = (duration, userid, ontick) => new Promise(res => {
const
start = new Date().getTime(),
iid = setInterval(
() => {
const delta = new Date().getTime() - start;
if (delta < duration) {
//if you want to trigger something each time
ontick(delta, userid);
} else {
clearInterval(iid);
res(userid);
}
}, 500)
;
});
You do not even need a promise, a simple function will do as well, but then you have to build some solution for triggering stuff when the timer is elapsed.
Thanks #Chev and #philipp these are both good answers.
I was also made aware of a technique where you use an array for the setInterval variable.....this would make my code as follows;
let intervals = []
let secondsLeft = 300000;
intervals['i'+userId] = setInterval(() => {
secondsLeft -= 1000;
if (secondsLeft === 0) {
console.log("now exit");
clearInterval(interval);
}
}, 10000);
Does anyone else foresee this working?.
UPDATE 6.56pm PST.....it works!!
I want to start timer after x interval seconds.This x interval seconds will come from server side.
Now i have some process going on server side and on page load i call getData method which starts a timer based on isRunning flag and i display progress
untill i found isRunning false and then stop a timer.
So if user is already on my page where i have 1 schedule jobs which will run after x seconds so i want this getData to call after that x seconds.Right now once user comes on the page getData keeps on going server side for getting progress for schedule jobs.
Hence i was thinking that i will get total seconds of first schedule job and configure my timer to start getData method after x seconds if user doenst refresh the page.
But here i am not getting how to configure $scope.startTimer method in such a way that it will start after x seconds.For eg:If schedule job will run after an hour then start timer method should only start after 1 hour and keep calling getData method every 2 seconds.
Below is my code:
function getData() {
myService.get(function (response) {
if ($scope.isRunning)
$scope.startTimer();
else
$scope.stopTimer();
//response.totalSeconds;here i will get total seconds after which i want to call this method again to show progress of schedule job
});
}
var stop;
$scope.startTimer = function () {
// Don't start a new timer
if (angular.isDefined(stop)) return;
stop = $interval(function () {
if ($scope.refreshTimer > 0) {
$scope.timerLabel = false;
$scope.refreshTimer = $scope.refreshTimer - 1;
} else { //REFERSH CALL
$scope.stopTimer();
getMockProgress();
}
}, 2000);
};
$scope.stopTimer = function () {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
};
Update :
else
$scope.stopTimer();
if (response.milliSeconds > 0)
setTimeout($scope.startTimer, response.milliSeconds);
But this fails to call startTimer method after x milliseconds.
I will appreciate any help :)
I've made this system so users can login to my website and play a game that requires some interval timing. When the user is done with playing I basically want to kill the interval. While everything seems to be running fine, there is something wrong with killing the interval.
Here is the problem Whenever a user is done playing the interval gets killed, not only for the user playing but for everyone. This might be because I'm assigning a variable to the interval and when a user is done playing a game I'm killing the interval, am I right that it then would kill the other intervals as well?
Here is some code I've written for this question,
var user; //this is a variable that has all info about the user. (its not usually empty)
var usersPlaying = [];
socket.on('game', function(game) {
if(game.type == "start"){
usersPlaying.push({
user_id: user.id
});
var game = setInterval(function(){
if(findUser(user.id) !== undefined){
console.log('Second passed!');
}else{
clearInterval(game); //stop the interval
}
}, 1000);
}else if(game.type == "stop"){
console.log("User has decided to quit playing the game!");
usersPlaying.splice(usersPlaying.findIndex(user => user === user.id), 1); //remove user from playing
}
});
There might be some mistakes in there since I rewritten and simplified the code otherwise it would be way to hard to help me out.
Anyways, how can I make it so it only clears the interval running for a certain specified person?
Thanks!
The setInterval call returns a unique id. You can use that id to clear that interval timer afterwards:
var uniqueId = setInterval(function () { /* ... */ }, 1000);
Later on ...
clearInterval(uniqueId);
will kill that specific timer.
I suggest storing the uniqueId for each user inside the usersPlaying array.
Store the interval for that specific socket inside its own scope :
var user; //this is a variable that has all info about the user. (its not usually empty)
var usersPlaying = [];
socket.on('game', function(game) {
if(game.type == "start"){
usersPlaying.push({
user_id: user.id
});
socket.game = setInterval(function(){
if(findUser(user.id) !== undefined){
console.log('Second passed!');
}else{
clearInterval(socket.game); //stop the interval
}
}, 1000);
}else if(game.type == "stop"){
console.log("User has decided to quit playing the game!");
usersPlaying.splice(usersPlaying.findIndex(user => user === user.id), 1); //remove user from playing
}
});
So you can also kill it when disconnections occur :
socket.on('disconnecting',function(){
if(socket.game){clearInterval(socket.game);}
});
EDIT :
var user; //this is a variable that has all info about the user. (its not usually empty)
better store all that inside the scope of the socket (each client socket object in the server will have its own "user" key instead of making use of ugly global variables
So store it like socket.user = {id:"foo"} and you can access the specific user object for that client performing the socket event request like if(findUser(socketuser.id) !== undefined){
I'm working on a chatbot script (Hubot - running in terminal) exercise and looking for a method to count the time since the last message was left in the thread. Then after nobody has left a message for X number of minutes (let's say 10,000 milliseconds) I would like to console.log("CRICKETS!..CRICKETS!..")
I'm imagining something like:
//currentTime - startTime = timeSince
//and
// if( timeSince > 10,000)
// {console.log("Crickets!..")
however I'm not sure of how to create the currentTime variable as continuously growing counter
Below is the code I've started which doesn't appear to throw any errors in the , but also doesn't seem to work as I'm running it in the terminal. It just prints the current time twice
module.exports = function(robot) {
return robot.hear(/$/i, function(msg) {
var startTime = (Date.now()) ;
return(startTime);
if (Date.now() - startTime > 1000) {
console.log("CRICKETS..!...")
};
});
};
You'll notice I'm using Date.now() but I'm not attached if there's a better method. Also here is a link to basic hubot scripts in case it is needed for context - https://github.com/github/hubot/blob/master/docs/scripting.md
You can always use setTimeout and cancel it if need be
Pseudo-code:
var myTimeout = setTimeout(function () {
//nobody has left a message for 10 seconds
}, 10000);
if (user has left message)
clearTimeout(myTimeout);
The window.setTimeout function allows you to trigger a callback function after a delay. And you can clear that timeout by calling window.clearTimeout(value_returned_by_setTimeout).
We could define a callback: function crickets(){ console.log('Chirp! Chirp!'); }
Assuming some function newMessage gets called whenever a a new message appears, you could try something like this:
var cricketTimeout = null;
function newMessage(){
//... your code
if (cricketTimeout) clearTimeout(cricketTimeout);
cricketTimeout = setTimeout(crickets, delayInMilliseconds);
}