pythonflaskflask-migrate

Flask-migrate upgrade fails because the application needs to run code that modifies the db on startup


I have a Flask application that needs to run code on startup. In my case, it detects available cloud resources and writes those to a table in a database.

The problem is that when I run flask db upgrade, then flask-migrate executes the application startup code, including the code that tries to write to the db table. Since the migration itself is what creates the table, the table doesn't exist yet, and the migration fails.

Here is the code, with irrelevant parts removed:

def create_app():
    app = Flask(__name__, static_url_path=None)
    with app.app_context():
        db = set_up_database_connection()

    Migrate(app, db)
    
    # This is what fails because the table doesn't exist yet
    run_startup_tasks()

    @app.get('/')
    def health_check():
        return 'OK'

    app.logger.info("Application created.")
    return app

I did a temporary workaround by using the @app.before_first_request annotation. With the workaround, the startup code runs just before the first request comes through. This is not ideal, though, since that causes the first request to the application to take a long time.

 @app.before_first_request
 def perform_startup_tasks():
     run_startup_tasks()

How do I run startup tasks that require the database without breaking flask-migrate?


Solution

  • I ended up solving this problem by just creating a separate file, which runs the startup tasks:

    app = Flask(__name__, static_url_path=None)
    with app.app_context():
        db = set_up_database_connection()
    
    run_startup_tasks()
    

    This file is run before the main application is run, and after the migrations are run:

    flask db upgrade && python run_startup_tasks.py && flask run
    

    This fixes the problem, since the main application (which flask-migrate uses) doesn't run startup tasks. It's run in a separate script.