Meteor: observe a collection with reactiveVar - javascript

I have an application in which a user can manage multiple alarms (set a new alarm, edit it, or snooze)
When the alarm time is reached I need to notify the user. If a user clicks snooze, the time_end field gets 5 minutes added to it.
How can I track when the alarm times have been reached?
I have tried using a collection.observe() - but it only works once, on server start
Server: Meteor Startup
var expiredAlarms = Alarms.find({$and: [{"time_end": {$lt: moment()._d}}, {notification_sent: false}]});
expiredAlarms.observe({
added: function(doc) {
console.log('alarm timeout has been reached');
processAlarmEnd(); //set notification_sent to true
},
removed: function(doc) {
console.log('A notification has been sent');
}
});
The above code only works when the app is started and processes all notifications for expired alarms - but once new alarms expire, nothing happens. My guess is because moment()._d does not change and the same old query is called over and over again.
Should I place this code in a Tracker.autorun - will that help? Any suggestions on doing this better/smarter?

To make code execute in the future, you need to use setTimeout. In your observe query, don't care about the time, and in the added callback, calculate how many milliseconds remains till the alarm should go off, and use setTimeout to call processAlarmEnd after that amount of milliseconds.
You may also need to cancel a setTimeout with clearTimeout in the removed callback.

Related

Discord javascript l Deleting data from database after the time has expired

I made a premium membership system to my discord bot, but the time starts to be minus a certain time, so I want to delete the data from the database when the time I set with ms expires. I tried something like that but it didn't work
I save the data as follows;
Looks like you are setting the interval to an incredibly long time. It looks like you are storing the specific time you want the function to run. You'll probably want to do something like this:
let interval = sure - new Date();
if(interval < 0) { // this expiration date already passed
interval = 0;
}
setInterval(function() {
db.delete(` ... `);
db.delete(` ... `);
}, interval);
However! If you do all this multiple times (like inside the 'message' handler like you're doing right now), you're gonna have a memory leak. Make sure you are setting the intervals only once.
Also, if your program crashes, you'll have to set up all the intervals again at startup.
If I was making something like this, I would instead make a cron job to check only once per day to delete all the expired members, instead of using setIntervals.

In Angular 5 , How should group number of click events and emit once only when user stop clicking

I have a angular application (Angular5 + ngrx5).
In my app, users can click/select are number of options/items (just simple divs). such as option1, option2, option3 .... Multiple options can be selected.
Currently, users select one option, we trigger a service call to save a selected option. We do currency version number checks, so users have to wait the service call response (with latest version number) back before select the next option. It is not providing good UX.
Therefore, I prefer that users can keep clicking a number of options, once users stop clicking we make a single service call with multiple selections .
My question is that how to group number of click events and emit once only when user stop clicking? any examples or any suggestions?
I know rxjs debounce can drop emitted values.clicks, but I do not want to drop them I want to aggregate them in order to make a single service call.
thank you
The rxjs way of achieving this.
const ajax=Rx.Observable.timer(4000).mapTo('ajaxcall')
Rx.Observable
.fromEvent(click, 'click')
.scan((acc,curr)=> ([curr,...acc]) ,[])
.debounceTime(500)
.mergeMap(arrClick=>{
console.log(arrClick)
return ajax
}).subscribe()
https://jsfiddle.net/7kbg4q2e/453/
You can handle this with a setTimeout.
On each click, you can build an array with your values.
Then, set a timer to send to the API. If it receives another request while waiting for that timer, cancel it, and start a new one.
handleClick(value) {
this.values.push(value);
// If there's a timer going, cancel it
if (this.timer != null) {
clearTimeout(this.timer);
}
// Start a new one
this.timer = setTimeout(() => {
// Send to your API
// Make sure to clear your this.values array after the API call has returned
}, 5000);
}
In the example above, it will only send the request after 5 seconds without a click event

EventEmitter.once() inside a setInterval for read data at requested time intervals

I have this code:
device.on('found', success => {
success.once('updated', data => {
console.log('Got data ' + data);
});
});
The problem is that 'device' is a bluetooth device that sends data every second.
So every time i found a device I start listening for updates and every update I have my data.
I want that my device continues to share data every seconds but, how I can read one 'update' every 10 minutes (for example)?
If I put succes.on(), the code inside will be called every second... If I put succes.once(), the code is called only once, I tried to put this function inside a setInterval but it doesn't work...
My goal is to read data posted from an event emitters whet I want, and not when he post, It is correct that it continues posting but I want read at some specific time intervals...
Some helps?
Thank you!

how can I make a countdown timer perform an action when it runs out?

this is my very first question here and may not meet some standards, for that i apologize in advance.
I have a site developed in laravel 5 where the users register and are expected to make take an action within a specific period after registration. I have included a countdown timer for that purpose (the time code is shown below). Now I need to automatically remove a user record from the database when the time runs out. Please how can I do that?
the timer code is:
<div class="getting-started"></div>
<?php
$time = strtotime($user['updated_at'].'+24 hours');
$countdown = strftime('%Y/%m/%d %H:%M:%S',$time);
?>
<script type="text/javascript">
$(".getting-started")
.countdown("{{$countdown}}", function(event) {
$(this).text(
event.strftime('%H:%M:%S')
);
});
</script>
If you want something to happen on the server, then you should maintain the timer on the server side, not the client side. Otherwise, the user can simply change the timer or otherwise block the action that the expiration is meant to trigger. I would store a timestamp with the user record, noting when it was created. Then write a script to loop over all records that are older than your threshold and perform the desired action on them. Then run this script via a cron that fires at a regular interval.

Continually check for an Oracle record at page load

I basically have a page that when loads, reads an Oracle SQL table for a specific record id that may not currently exist at the point as it may take up to a minute to insert this specific record into the table.
Based on this, I need a means of showing a "Loading Image" while it waits for the record to exist, so has to wait. Once it does, I want to remove the loading image and present the user with the record details. I am using Oracle Application Express 4.2 for this.
My question is not so much the loading/hiding of the image but how to continually check for the record within the Oracle table, during page load.
Either I receive the record successfully and then hide the image or say after 1 minute, I dismiss the checking of the record and present the user with a message indicating that no record was found.
Sorry for my english. I will try help you.
Make your "Loading image" always visible on the page. There is no need to show it on load, you only need to hide it at proper moment.
Add Application Process to your application. Name it for example "GET_MY_ROW". Process must check your event, and return some flag, for example 1 or 0.
Example:
declare
l_cnt number;
begin
select count(*)
into l_cnt
from table1 t
where id = 12345;
if l_cnt > 0 then
htp.p(1);
else
htp.p(0);
end if;
end;
3.3 Add javascript code as page load event (for example by Dynamic Actions):
Javascript code:
var myInterval = setInteral(function {
var get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=GET_MY_ROW',$v('pFlowStepId'));
get.GetAsync(function(pRequest) {
if (pRequest.readyState == 4) {
if (pRequest.responseText == 1) {
alert('Record loaded successfully');
// add function call, hiding your "Loading image" here
clearInterval(myInterval);
}
};
});
get = null;
}, 5000); //check every 5 seconds
setTimeout(function() {
alert('Sorry, no record was found. Try again later.');
clearInterval(myInterval);
}, 60000); // fail after 1 minute
Since NoGotnu already answered, I'll put this here:
Is there any reason for the procedure to be called through a job? Is it the only way to create the required record? Is the job called anywhere else? Why not call the procedure directly when the required page has been submitted and show the loading icon there? When it finishes, the user knows it has finished. That would involve a lot less fiddling around as you can make apex show a processing graphic on page submit. You could then just inform the user on the other page that the process has not been ran yet and they'd have to do that first.
Secondly, while NoGotnu's answer will work, I'd like to point out that in apex 4.2 you should use the apex.server namespace instead of the never documented htmldb_Get construction. apex.server.process is a clean implementation of the jQuery ajax setup.
NoGotnu's code translated:
apex.server.process( "GET_MY_ROW"
, null
, { dataType: text
, success: function(pData){
if (pData == 1) {
clearInterval(myInterval);
alert('Record loaded successfully');
};
}
}
);
The call doesn't really need to be async though, but ok.
Another option would be to implement a "long poll" instead of firing the ajax event every 5 seconds. A long poll will just initiate a call to the server and wait for a response. As long as the server is busy, the client will wait. To achieve this you could use dbms_alert, as suggested in Waiting for a submitted job to finish in Oracle PL/SQL?
You'd signal an alert in the plsql code of the job, and in the ondemand process code register an interest in the alert and use waitone/any with a 60 second timeout. Presto long poll.

Categories

Resources