VOLTTRON Csv Driver Agent scheduled task - volttron

Is there a way I could call an agent to start a certain time every day?
For example I would like to create an agent that creates an API call at 4AM everyday (to openweathermap) to check the hourly forecast for the day. Basically if the hourly forecast yield's ideal conditions the agent could do building pre-cooling... Else if the hourly weather conditions starting at 4AM through the afternoon hours are not ideal the agent would not do anything (pass). Hopefully that makes sense! just one API call at 4AM to make some decisions, else pass.
Also having some extra logic if current time equals a winter month to pass as well. datetime.datetime.now().month?
##Core.receiver("onstart")
def onstart(self, sender, **kwargs):
"""
This is method is called once the Agent has successfully connected to the platform.
This is a good place to setup subscriptions if they are not dynamic or
do any other startup activities that require a connection to the message bus.
Called after any configurations methods that are called at startup.
Usually not needed if using the configuration store.
"""
# Every 120 seconds, ask the core agent loop to run the actuate point method with no parameters
self.core.periodic(600, self.actuate_point)
def actuate_point(self):
"""
Request that the Actuator set a point on the CSV device
"""

You could use the built in cron scheduler (https://volttron.readthedocs.io/en/main/developing-volttron/developing-agents/agent-development.html?highlight=cron#periodics-and-scheduling). This uses the same style of cron that your linux system uses. Put the following decorator on your function and the specified cron will just work.
from volttron.platform.scheduling import cron
#Core.schedule(cron('0 1 * * *'))
def cron_function(self):
print("this is a cron-scheduled function")
Some useful crons are located https://crontab.guru/examples.html

Related

How to resolve a Salesforce flow error where Flow calls an apex class

I have a flow which calls an apex class and here is execution logs error,how to resolve this error
Error Occurred During Flow "ServiceAppointment_API": An Apex error occurred: System.AsyncException:
Warning: Approaching hourly email limit for this flow.
Each flow in your organization is limited to 100 error emails per hour. Since 12:00 PM, Salesforce has sent 99 error emails for ServiceAppointment_API flow. After 100 emails, Salesforce suppresses all error emails for this flow. The limit resets at 1:00 PM.
Error element myWaitEvent_myWait_myRule_3_event_0_SA1 (FlowActionCall).
An Apex error occurred: System.AsyncException: You've exceeded the limit of 100 jobs in the flex queue for org 00D36000000rhGR.
Wait for some of your batch jobs to finish before adding more. To monitor and reorder jobs, use the Apex Flex Queue page in Setup.
Your helps is appreciated
Regards,
Carolyn
The apex class schedules some asynchronous (background) processing. Could be a batch job, could be method annotated with #future or something called Queue able. You can have up to 100 of these submitted and up to 5 active (running) at given time.
It's hard to say how to fix without seeing the code.
Maybe the #future isnt needed, the developer meant well but something went wrong. Maybe it has to be async but could be done with time-based workflow or scheduled action in process builder?
Maybe it's legit your bug, that code could be rewritten to work faster or process more than 1 record at a time.
Maybe it's not your fault, maybe there's a managed package that scheduled lots of jobs and next ones fail to submit.
Maybe you'll need to consider a rewrite that detaches it but more. Say instead of almost instant processing - have code that runs every 5 minutes, checks if there's something recently changed that needs processing and does it.

How to let user set time to run a task in google app engine

My customer wants to set time (ex: Dec 13, 16:00 pm) to run a certain task.
I dont think cron job fits for it because customer dont know how to use google app engine SDK.
Is there any other way to do it?
Thanks
You can create a task and set the time when you want this task to be executed. From the documentation:
X-AppEngine-TaskETA, the target execution time of the task, specified
in milliseconds since January 1st 1970.
You can use the task queue API: https://cloud.google.com/appengine/docs/python/taskqueue/ or even the defer API: https://cloud.google.com/appengine/articles/deferred
If your customer is a user of your application, and there may be several users requesting tasks to be executed at different times, then you can save these requests to the datastore. Create a cron job to run every hour (or however precise you need the timeframe) which checks the datastore to see if there are any tasks to run at that time - if so, run the proper script.
If this is just a one-time, or small number of tasks, you can do as Andrei suggested.

How to recover Go timer from web-server restart (or code refresh/upgrade)?

Consider a web service, for instance, where user can make an API request to start a task at certain scheduled time. Task definition and scheduled time are persisted in a database.
First approach I came up with is to start a Go timer and wait for the timer to expire in a Goroutine (not blocking the request). This goroutine, after time expiration, will also fire another API request to start executing the task.
Now the problem arises when this service is redeployed. For zero downtime deployment I am using Einhorn with goji. After code reload, obviously both timer goroutine and timer-expiration-handler goroutine dies. Is there any way to recover Go timer after code reload?
Another problem I am struggling with is to allow the user to interrupt the timer (once its started). Go timer has Stop to facilitate this. But since this is a stateless API, when the \interrupt request comes in service doesn't have context of timer channel. And it seems its not possible to marshal the channel (returned from NewTimer) to disk/db.
Its also very well possible that I am not looking at the problem from correct perspective. Any suggestions would be highly appreciated.
One approach that's commonly used is to schedule the task outside your app, for example using crontab or systemd timers.
For example using crontab:
# run every 30 minutes
*/30 * * * * /usr/bin/curl --head http://localhost/cron?key=something-to-verify-local-job >/dev/null 2>&1
Using an external task queue is also a valid option like #Not_a_Golfer mentioned but more complicated.

How do I execute code on App Engine without using servlets?

My goal is to receive updates for some service (using http request-response) all the time, and when I get a specific information, I want to push it to the users. This code must run all the time (let's say every 5 seconds).
How can I run some code doing this when the server is up (means, not by an http request that initiates the execution of this code) ?
I'm using Java.
Thanks
You need to use
Scheduled Tasks With Cron for Java
You can set your own schedule (e.g. every minute), and it will call a specified handler for you.
You may also want to look at
App Engine Modules in Java
before you implement your code. You may separate your user-facing and backend code into different modules with different scaling options.
UPDATE:
A great comment from #tx802:
I think 1 minute is the highest frequency you can achieve on App Engine, but you can use cron to put 12 tasks on a Push Queue, either with delays of 5s, 10s, ... 55s using TaskOptions.countdownMillis() or with a processing rate of 1/5 sec.

How can I do the same thing over and over every 1-4 seconds in google app engine?

I want to run a script every few seconds (4 or less) in google app engine to process user input and generate output. What is the best way to do this?
Run a cron job.
http://code.google.com/appengine/docs/python/config/cron.html
http://code.google.com/appengine/docs/java/config/cron.html
A cron job will invoke a URL at a
given time of day. A URL invoked by
cron is subject to the same limits and
quotas as a normal HTTP request,
including the request time limit.
.
Also consider the Task Queue - http://code.google.com/appengine/docs/python/taskqueue/overview.html
Reconsider what you're doing. As Ash Kim says, you can do it with the task queue, but first take a close look if you really need to run a process like this. Is it possible to rewrite things so the task runs only when needed, or immediately, or lazily (that is, only when the results are needed)?

Resources