Search code examples
pythonflaskapscheduler

Stop apscheduler job from another .py file method


I'm creating a apscheduler job in one function, call this function in a flask app in before_first_request(). This job triggers a function every 30 seconds (which is in another .py file in my flask app). Based on one particular result (from yet another .py file), I have to terminate this apscheduler job.

In app.py:
@myapp.before_first_request
def before_first_request():
    ..
    ..
    check_conn()

then in checking.py, I'm creating and starting a Background_scheduler job.
def check_conn():
    with myapp.test_request_context():
        global process_scheduler
        process_scheduler = BackgroundScheduler()
        process_scheduler.add_job(func=send_conn_check, trigger="interval", seconds=10, id='conn_job')
        process_scheduler.start()
        atexit.register(lambda: process_scheduler.shutdown())

this 'send_conn_check' is in sendxx.py:
def send_conn_check():
    ....  # sends message at regular time interval
    ....

When a message is received for first time in backgrnd.py, the below function will do some work and then call 'check_state' method to remove the apscheduler job,
def call_conn_accept(ch, method, properties, body):
    try:
        print('Connection message from abc %r' % body)
        json_str = body.decode('utf-8')
        ...
        if accept == "ACCEPT":
            check_state()  # this function is defined in checking.py

Again in checking.py, 
def check_state():
    global process_scheduler
    process_scheduler.remove_job(job_id='conn_job') ####  At this point I have remove the process_scheduler job. 
    ....
    ....

node1_CONN # Scheduler sending message

node1_CONN

node1_CONN

ERROR:root:An exception has occurred:("name 'process_scheduler' is not defined",) # when process_scheduler in check_state() in checking.py is called to remove the apscheduler job.

Connection message from abc '{"node1": "ACCEPT"}'

node1_CONN # Once the above message has been received, the scheduler should remove the job, but it doesn't. It again sends 'node1_CONN'

ERROR:root:An exception has occurred:("name 'process_scheduler' is not defined",)

Connection message from abc'{"node1": "ACCEPT"}' ... ...


Solution

  • I solved it by placing the logic in a Multiprocessing process in python and also starting a thread inside this multiprocess daemon to call the 'send' function every x seconds and cancelling the thread when a condition is met inside another function of the same multiprocess daemon..

    from multiprocessing import Process
    
    class processClass:
        def __init__(self):
            print("Starting the multiprocess app...")
            p = Process(target=self.run, args=())
            p.daemon = True                       # Daemonize it
            p.start()                             # Start the execution
    
      def run(self):
            #with myapp.test_request_context():
            print('listening...')
            send_conn_check()                     # Calling send function thread 
            listen_state()                        # Calling receive function.
    
    def send_conn_check():
        global t                              
        t = threading.Timer(10, send_conn_check)  #Thread
        t.daemon = True
        t.start()
        ...
        ...
    
    def listen():
      try:
        ...
        ...
        if accept == 'ACCEPT':
            t.cancel()                           # Cancel the thread when a condition is met
            check_state()