setInterval Stops After An Hour With Electron - electron

Hoping someone can point me in the right direction here. My electron app needs to perform an API call every 10 minutes or so. I currently do this using a setInterval loop in the renderer process that fires every 10 minutes.
It generally works fine, for a few hours before it seems to just stop firing. I have several processes that clear and restart the setInterval to try and counteract the problem, but nothing seems to work.
The app opens new browser windows and displays content, which mean the main window may not be in focus all the time, which I suspect may have something to do with it.
I have tried adding
powerSaveBlocker.start("prevent-display-sleep");
powerSaveBlocker.start("prevent-app-suspension");
to my main electron js script, but it doesn't seem to have an effect. The problem is mostly being displayed on Windows machines. I'm not entirely sure if it happens on Mac or Linux.
So my question, is there any reason why this would be happening that intervals just die after a point? The powerSaveBlocker calls made sense to me, but they don't really seem to do anything.
Or is there a better way to have a background process running at intervals that can perform these API calls? I had looked at node-schedule but I'm not sure if it will fix this issue.

Answering my own question here with credit to #snwflk who pointed me in the right direction in a comment on the original post.
Whilst I have not been able to clarify with absolute certainty this solves the problem, I have also not seen the problem since. (It's not always 100% reproducible, and its difficult to test as it requires a machine, left alone for several hours, which may or may not display the problem).
I have however rolled the fix out to a few customers and their machines seem to still be online days later, which is a good sign.
So, the solution was to disable backgroundThrottling on the main BrowserWindow object (interval was running in the renderer processes)
Docs: https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
An example
mainWindow = new BrowserWindow({
webPreferences: {
backgroundThrottling: false,
},
});
FYI be warned there have been a few bugs that prevented this setting from working, ie https://github.com/electron/electron/issues/20974 so be sure to update your electron version.

As far as I know intervals should keep running forever (the MDN page also doesn't mention anything).
If I understood correctly, your Electron app only does that API call? So it would be hard to tell the difference between the interval not triggering, and some other problem causing a freeze?
My guess would be you have an uncaught exception being thrown, or some other similar error or event. https://stackoverflow.com/a/43911292/841830 gives some suggestions of things to catch. https://github.com/sindresorhus/electron-unhandled says it can be used in both main and renderer processes to catch and report all problems.
Or is there a better way to have a background process running at intervals that can perform these API calls?
If you were on Linux, using cron to run a node script (or even just a wget or curl command) would be better than using an Electron app just for this. Task scheduler seems to be the windows equivalent of cron.

Related

Run Rufus-Scheduler with Ruby on Rails

I'm trying to make a application that serves as an REST API, which is related to information regarding X.
Simultaneously, I'd like to schedule some task to be run from time to time so that it retrieves remote information and inserts it into the database.
Looking as a very atractive solution for a begginer like me, I decided to Rufus as in https://github.com/jmettraux/rufus-scheduler#so-rails.
Firstly, I started by doing some dummy code, to test it out, and it appeard to work as intented.
First Try
The problem was after this, I tried doing so, but adding some real logic to it - "some task to be run from time to time so that it retrives remote information and inserts it into the database."
Here is when the issue begins: after the (usually) very first execution, the app doesn't do anything else - it even stops answering to REST requests. Then, as soon as I press Ctrl-C, it immediatly makes up for what it hasn't done, as in: does the "pending" tasks, printing the first logger.info as if it was in the intented time - although the insertion in the database only happens after I do this action of pressing Ctrl-C -, and answers to the REST requests.
After searching through the internet, I haven't found anything close to my problem, I believe I have some misconfiguration, or maybe I'm not running things as intented.
EDIT: Turns out I'm stupid and was pausing the program's execution, by selecting the terminal's text, as it was my first time developing on Windows.

Frequently refreshing web page during long-running process

I've been hunting around my issue for a while, probably the best I've come up with is another Stack Overflow question: How should I perform a long-running task in ASP.NET 4?
I'm in a similar place in that I'm wanting to understand what my options are, but I don't feel I know enough specifically about MVC to come to a view. I'm using MVC 5 but with the 4.8 framework, plus I note that technologies such as SignalR have become available since this question was asked. I was wondering if any experienced MVC'ers could give me a view?
I too have a long running process. More specifically, the user is importing a file. The file is delimited so the import happens line by line. The file might be thousands of lines long. Each line will be parsed and imported in a fraction of a second but the whole operation might take several minutes.
I don't particularly need behaviour to be asynchronous, but because of the length of the entire process I want to regularly update the user on progress. I'm wondering what options I have?
I've got a vague recollection that I might have looked at this problem 20-odd years ago (Classic ASP), and solved it by regular flushes, sending a bit more of the page to the client every few seconds, but I'm trying also to use a _Layout page now, so I've sent the page back already. So I don't think I have that option, even assuming such a mechanism still exists. A bit more recently, but still a while ago, I might have used javascript to poll but everything I'm reading now seems to point me to newer technologies which I'm not sure I fully understand yet.
I'm just wondering how would you solve this problem?
I would not be performing any of the file parsing on the web server, especially if it's thousands of rows long. I would delegate this to a background service of sorts, whether that be a Lambda service in the cloud or a Windows service or a scheduled task. You could then call your SignalR hub from the background task (whatever that might be) to update the progress of the import.

CloudKit 'Unexpected Server Error' Anytime Manual Operations Performed in Dashboard

I have been developing an iOS app that utilizes the CloudKit feature available for Apple Developers. I've found it to be a wonderful resource, especially since the very day I started designing my backend, the service I was intending to use (Parse) announced it was shutting down. It's very appealing due to it's small learning curve, but I'm starting to notice some annoying little issues here and there so I'm seeking out some experts for advice and help. I posted another CloudKit question a couple days ago, which is still occurring: CloudKit Delete Self Option Not Working. But I want to limit this to a different issue that may be related.
Problem ~ Ever since I started using CloudKit I have noticed that whenever I manually try to edit (delete an entry, remove or add part of a list, even add a DeleteSelf option to a CKReference after creation), and then try to save the change, I get an error message and cannot proceed. Here is a screenshot of the error window that appears:
It's frustrating because anytime I want to manipulate a record to perform some sort of test, I either have to go do it through my app, or just delete the record entirely and create a new one (that I am able to do without issue). I have been just working around this issue for over a month now because it wasn't fatal to my progress. However, I am starting to think that this could be related to my other CloudKit issues, and maybe if I could get some advice on how to fix it I could also solve my other problems. I have file numerous bug reports with Apple, but haven't received a response or seen any changes.
I'd also like to mention that for a very long time now (at least a few days), I've noticed down in the bottom left hand corner of my Dashboard that it is consistently saying that it's "Reindexing Development Data". I remember at first that wasn't an issue, I would get that notification after making a change but it'd go away after the operation is complete. Now it seems to be stuck somewhere inside the process. And this is a chronic issue, it's saying this all the time, even right when I log into my dashboard.
Here is what I'm talking about:
As time goes on I find more small issues with CloudKit, I'm concerned that once I go into production more problems could start manifesting and then I could have a serious issue. I'd love to stick with CloudKit and avoid the learning curve of a different service like Amazon Web Services, but I also don't want to set myself up for failure.
Can anyone help me with this issue, or has anyone else experienced it on a regular basis? Thanks for the advice and help!
Pierce,
I found myself in a similar situation; the issue seemed to be linked to Assets; I had an Asset in my record definition. I and several other I noted reported the re-indexing issue on the apple support website and after about a month it eventually disappeared.
Have you tried resting your database schema completely, snapshot the definition; since you zap it completely and than reset, see inset.
Ultimately I simply created a new project, linked it to cloud kit and use the new container in my original app.

Avoid app throttling when Electron is in background

Consider the following example:
setInterval(function()
{
console.log(new Date());
});
If I run it with electron example.js under OS X, it opens up an icon in my dockbar and starts printing out the time on the console. If the app is not focused, however, after a while it starts throttling.
I looked around and found that this is due to OS X power saving strategy. Now, what if I needed it to keep working in background? My app will be a daemon doing a little bit of something every now and then, and I can't have my users blankly staring at my app for ages.
I found out here that I can do
electron.powerSaveBlocker.start('prevent-app-suspension');
Which actually fixes my problem. This however, is quite invasive, since as far as my understanding goes it prevents the system from sleeping at all! I don't need this much, I would just need my app to do something when the computer is active and online without forcing it to stay awake forever.
Isn't there anything in the middle, between having my users keeping the app continuously in the foreground, and making their computer sleepless forever?
As per the current docs:
Note: prevent-display-sleep has higher precedence over
prevent-app-suspension. Only the highest precedence type takes effect.
In other words, prevent-display-sleep always takes precedence over
prevent-app-suspension.
For example, an API calling A requests for prevent-app-suspension, and
another calling B requests for prevent-display-sleep.
prevent-display-sleep will be used until B stops its request. After
that, prevent-app-suspension is used.
What this means is that setting prevent-app-suspension to on, will still allow the system to sleep, and simply does what you desire it to. You can however run the function twice, passing both flags, turning both options on. However, as the docs above say, if both are set to on, then the system will not sleep until that flag has been removed.

any better timer in asp.net?

I used System.Timers.timer in global.as in asp.net to set a timer for scheduling execute a
function
let' say transferMoney().
But it seems that this timer might stop after several hours unexpected.
And this cause that all the actions are pending.
I want to know whether there are any better methods to set up a timer in asp.net, MVC 1.0?
Thanks in advance!
It might just be because the application got recycled. Global.ashx is not really the right place to do long running tasks because if your AppDomain gets recycled your timer will die. I suggest making a job windows service instead.
Edit: Well, it's fairly easy to create a windows service project in Visual Studio just do [File] > [Add] > [New Project...] > [Windows] > [Windows Service] and you will get the stub code for the project.
It's hard to come up with a complete example so i suggest you google it. ;) There are tons of samples out there for you to look at.
This article on CodeProject seems to be a good introduction to Windows Services.
Any timer you'll use in ASP.NET apps will eventually "terminate", but this a very expected behavior due to process recycling.
The timer will never work because IIS will reschedule the worker process regularly based on Application Pool settings, so when it recycles your timer will get destroyed and you might need to reopen it.
You can put a check on whether timer object is still available or not, if not available then create it !!, using any other timer object will not work. But this still has a problem, because if you dont have any web request for particular period of time, it will still get destroyed. Best is to setup a ping monitor from other place which can keep your website alive.
You can't reliably run a timer in ASP.NET. If there are no requests coming in, the IIS can shut down the application, and it will not start until the next request arrives.
Why do you think that you need a timer? In most web applications this is not needed at all to do periodical updates unless they depend on an external source.
If you are just moving data around inside your application, the actual transactions doesn't have to happen at an exact interval, you only have to calculate what the result would be if they had happened. Whenever a request comes in, you calculate how many transactions would have happened since the last request, and do them to catch up to the current state.
If your transactions rely on an external source so that they actually has to run at a specific time, you simply can't do it with ASP.NET alone. You need an application that runs outside IIS, for example started periodically by the windows scheduler.
You could try the system.threading.timer
http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx

Resources