apscheduler icon indicating copy to clipboard operation
apscheduler copied to clipboard

Feature Request: Manual start of a job

Open gsemet opened this issue 7 years ago • 7 comments

Is it possible to add an API to the scheduler to run an existing job. For example: a periodic task is scheduled every day. I'd like to give the ability of the user of start this job manually whenever it wants. If it is a long task and max_instances=1 is set, for instance, let if it was started by the normal schedule, at max 1 instance is started and any time.

Example:

scheduler.schedule_job(job_id)

Ref: #241

gsemet avatar Nov 12 '17 22:11 gsemet

I'd rather name it start_job() but otherwise this is fine.

agronholm avatar Nov 13 '17 07:11 agronholm

and a stop_job to interrup a running job (probably not the same as pause/unpause, which only impacts the scheduler)

gsemet avatar Nov 13 '17 23:11 gsemet

I'm not sure about that, because how do you stop a job that's running in a worker thread?

agronholm avatar Nov 14 '17 07:11 agronholm

Kill the thread ? At least document on best practice. I end up always doing the same : putting a stop Boolean, checked during the job. And a timeout (if not stopped after n seconds, kill the job)

gsemet avatar Nov 14 '17 07:11 gsemet

There is not way to kill threads in Python. So what would you expect stop_job() to do in that case? Put up a flag somewhere (where?) which the user code will voluntarily check and stop itself when it's set?

agronholm avatar Nov 14 '17 08:11 agronholm

stop flag is ok. So it is a user story, not an Apscheduler stuff. Please forget it

gsemet avatar Nov 14 '17 08:11 gsemet

I'm currently looking on how to do that, but I have no idea... Any workarounds before version 4.0 comes out?

daaa57150 avatar Jul 08 '19 17:07 daaa57150

My workaround is to call the job directly.

async def start_job(scheduler, job_id: str):
    job = scheduler.get_job(job_id)
    result = await job.func(*job.args, **job.kwargs)
    return result

An other way is to call add_job again with fields of the original except id and trigger. The parameter trigger=None is the same as DateTrigger(), and the job will be procced immediately.

async def start_job(scheduler, job_id: str):
    job = scheduler.get_job(job_id)
    scheduler.add_job(
        func=job.func,
        args=job.args,
        kwargs=job.kwargs,
        name=job.name,
        misfire_grace_time=job.misfire_grace_time,
        ...  # other fields except id and trigger
    )

huoguangjin avatar Dec 31 '22 07:12 huoguangjin

In v4.0 alpha, there's add_job() and run_job() which queue a job directly w/o scheduling. That should fulfill this feature request.

agronholm avatar Jan 01 '23 22:01 agronholm