Initialising the Database
Once the containers are running, the STELLA App database must be initialized before the application can be used.
The initialization process creates the required database schema and populates the database with initial data.
Initialize and Seed the Database
Run the following commands to initialize and populate the database:
sudo docker exec -it stella-dev-app-1 flask init-db
sudo docker exec -it stella-dev-app-1 flask seed-db
Command Implementation
The database initialization and seeding logic is implemented in the following module:
init_db()
Use this function to setup a database with set of pre-registered users.
Source code in app/web/app/commands.py
| def init_db():
"""Use this function to setup a database with set of pre-registered users."""
db.create_all()
|
seed_db()
Use this function to setup a database with set of pre-registered users.
Source code in app/web/app/commands.py
| def seed_db():
"""Use this function to setup a database with set of pre-registered users."""
# TODO: Make this more verbose and configurable
# add ranking systems to database
systems = []
for system_name in current_app.config["RANKING_CONTAINER_NAMES"]:
systems.append(
System(
name=system_name,
type="RANK",
system_type="LIVE",
num_requests=0,
num_requests_no_head=0,
)
)
for system_name in current_app.config["RANKING_PRECOMPUTED_CONTAINER_NAMES"]:
systems.append(
System(
name=system_name,
type="RANK",
system_type="PRECOM",
num_requests=0,
num_requests_no_head=0,
)
)
db.session.add_all(systems)
db.session.commit()
# add recommendation systems to database
systems = []
for system_name in current_app.config["RECOMMENDER_CONTAINER_NAMES"]:
systems.append(
System(
name=system_name,
type="REC",
system_type="LIVE",
num_requests=0,
num_requests_no_head=0,
)
)
for sysname in current_app.config["RECOMMENDER_PRECOMPUTED_CONTAINER_NAMES"]:
systems.append(
System(
name=sysname,
type="REC",
system_type="PRECOM",
num_requests=0,
num_requests_no_head=0,
)
)
db.session.add_all(systems)
db.session.commit()
|
Application Entry Point (Reference)
For context, the Flask application entry point used by these commands is defined here:
Configure loggers.
Source code in app/web/app/app.py
| def configure_logger(app):
"""Configure loggers."""
if app.config["DEBUG"]:
app.logger.handlers.clear()
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
log_format = "[%(asctime)s] %(levelname)s in %(module)s: %(message)s"
formatter = logging.Formatter(log_format)
handler.setFormatter(formatter)
app.logger.addHandler(handler)
app.logger.info("Logging setup for debug complete.")
else:
del app.logger.handlers[:]
gunicorn_logger = logging.getLogger("gunicorn.error")
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
app.logger.info("Logging setup complete.")
|
create_app(config_name=None)
Create application factory, as explained here: http://flask.pocoo.org/docs/patterns/appfactories/.
:param config_object: The configuration object or dictionary to use.
Source code in app/web/app/app.py
| def create_app(config_name=None):
"""Create application factory, as explained here: http://flask.pocoo.org/docs/patterns/appfactories/.
:param config_object: The configuration object or dictionary to use.
"""
config_name_environment = os.getenv("FLASK_CONFIG", "test")
app = Flask(__name__.split(".")[0])
# Load the default configuration
app.config.from_object(config[config_name_environment])
# If a test config or other config object is provided, load it
if config_name:
if isinstance(config_name, dict):
app.config.update(config_name)
else:
app.config.from_object(config[config_name])
if app.config["DEBUG"] and app.config["SENDFEEDBACK"] and not app.config["TESTING"]:
print("Initializing and starting scheduler in app factory process")
scheduler.init_app(app)
scheduler.start()
print("Scheduler started in app factory process")
configure_logger(app)
register_extensions(app)
register_blueprints(app)
register_commands(app)
swagger_config = {
"headers": [],
"specs": [
{
"endpoint": "apispec",
"route": "/apispec.json",
"rule_filter": lambda rule: True,
"model_filter": lambda tag: True,
}
],
"static_url_path": "/flasgger_static",
"swagger_ui": True,
"specs_route": "/docs/",
}
Swagger(app, config=swagger_config, template={
"info": {
"title": "STELLA API",
"description": """API documentation for STELLA endpoints.
**Base URL:** /stella/api/v1
All endpoints are prefixed with this base path, except `/proxy`, which operates at the root level.
""",
"version": "1.0.0",
},
"servers": [
{"url": "/stella/api/v1", "description": "STELLA API base URL"},
{"url": "/", "description": "Root-level proxy"},
],
})
return app
|
register_blueprints(app)
Register Flask blueprints.
Source code in app/web/app/app.py
| def register_blueprints(app):
"""Register Flask blueprints."""
app.register_blueprint(main_blueprint)
app.register_blueprint(api_blueprint, url_prefix="/stella/api/v1")
return None
|
register_commands(app)
Register Click commands.
Source code in app/web/app/app.py
| def register_commands(app):
"""Register Click commands."""
app.cli.add_command(init_db_command)
app.cli.add_command(seed_db_command)
app.cli.add_command(index_systems)
|
register_extensions(app)
Register Flask extensions.
Source code in app/web/app/app.py
| def register_extensions(app):
"""Register Flask extensions."""
db.init_app(app)
migrate.init_app(app, db)
bootstrap.init_app(app)
return app
|