I was browsing the Frappe scheduler docs, looking for a way to schedule a event at a specific time (with precision in seconds). I am interfacing with an external service that has a Queries-per-Minute threshold. I am always trying to use the Frappe internals over external libraries, but I don’t see an obvious way to do this. I would be happy to contribute back a solution that adds an execute_at(datetime) method but would like some guidance on approach.
This runs every minute except at the top of the hour per the best practices for this particular API. 0-59 would run every minute. This method should absolutely be wrapped in the frappe.enqueue method, and most likely in the long worker queue. @JoEz gets the gold star for helping me out and for making this contribution in the first place.
from frappe.utils.background_jobs import enqueue
from frappe.core.page.background_jobs.background_jobs import get_info
if not is_queue_running("my_custom_app.utils.sync_now"):
frappe.enqueue("my_custom_app.utils.sync_now",
queue="long",
timeout=1000,
settings=settings)
def get_job_queue(job_name):
queue_info = get_info()
queue_by_job_name = [queue for queue in queue_info if queue.get("job_name") == job_name]
return queue_by_job_name
def is_queue_running(job_name):
queue = get_job_queue(job_name)
return queue and len(queue) > 0 and queue[0].get("status") in ["started", "queued"]
This structure came from the MNT team that I have refactored a bit to add some features. I like the “is running” check.
Scheduler needs to be running for any scheduled job to run.
If you want to wait for a function in the long queue to complete, you should check if its still running or not. Otherwise you may be adding unintended multiples onto the queue.