diff --git a/Dockerfile b/Dockerfile index 61c7427..1ba668e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,3 @@ COPY . /app/ # Expose port 5000 for the Flask app to listen on when running within the container EXPOSE 5000 - -# Define the command to start the container. Use gunicorn as the WSGI server to serve the Flask app -# CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"] -CMD ["python", "app.py"] diff --git a/app.py b/app.py index 32a0726..df0da57 100644 --- a/app.py +++ b/app.py @@ -15,6 +15,7 @@ import json import subprocess import semantic_version +import argparse app = Flask(__name__) @@ -70,7 +71,7 @@ def get_chain_watch_env_var(): return chain_watch -CHAIN_WATCH = get_chain_watch_env_var() +CHAIN_WATCH = [] # Clone the repo @@ -750,6 +751,7 @@ def start_update_data_thread(): update_thread = threading.Thread(target=update_data) update_thread.daemon = True update_thread.start() + return update_thread @app.route("/healthz") @@ -786,7 +788,57 @@ def get_testnet_data(): ) -if __name__ == "__main__": +def get_app_args(): + # setup the application args, providing 3 different commands that run the application in different modes + parser = argparse.ArgumentParser(description="Cosmos upgrade monitor") + + app_role_subparsers = parser.add_subparsers(title='subcommands', + description='valid app roles to run', + help='runs the application in various configurations', dest='command') + + # debug mode runs the application as a development server, with the cache setup as a simple in Python cache + app_role_subparsers.add_parser('debug') + # reader mode runs the application as a production Flask server, with the cache setup as an external store that is read from + reader_parser = app_role_subparsers.add_parser('reader') + # writer mode runs the application as a datastore writer, with the cache setup as an external store that is written to + writer_parser = app_role_subparsers.add_parser('writer') + + # add the filesystem cache location arg to reader and writer parsers + reader_parser.add_argument('--cache-location', dest='cache_location', default='/tmp/cosmos_upgrade_monitor_cache') + writer_parser.add_argument('--cache-location', dest='cache_location', default='/tmp/cosmos_upgrade_monitor_cache') + + return parser.parse_args() + +# Acts as a factory, returning the flask app with the cache configured as FSCache +# Can be called by gunicorn like so: +# gunicorn -b 0.0.0.0 -w 4 'app:get_production_flask_app("/tmp/cosmos_upgrade_monitor_cache")' +def get_production_flask_app(cache_location): + global cache + cache = Cache(app, config={"CACHE_TYPE": "FileSystemCache", "CACHE_DIR": cache_location}) + return app + +# Acts as a factory, returning the flask app with the cache configured as Simple +def get_debug_flask_app(): + global cache + cache = Cache(app, config={"CACHE_TYPE": "SimpleCache"}) app.debug = True - start_update_data_thread() - app.run(host="0.0.0.0", use_reloader=False) + return app + +if __name__ == "__main__": + args = get_app_args() + if args.command == "debug": + CHAIN_WATCH = get_chain_watch_env_var() + print("Running in debug mode") + start_update_data_thread() + debug_app = get_debug_flask_app() + app.run(host="0.0.0.0", use_reloader=False) + elif args.command == "reader": + print("Running Flask application with FSCache") + app = get_production_flask_app(args.cache_location) + app.run() + elif args.command == "writer": + cache = Cache(app, config={"CACHE_TYPE": "FileSystemCache", "CACHE_DIR": args.cache_location}) + CHAIN_WATCH = get_chain_watch_env_var() + print("Running as writer") + thread = start_update_data_thread() + thread.join() diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..ba2c655 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,18 @@ +services: + reader: + build: + context: . + ports: + - "5000:5000" + volumes: + - cache-volume:/var/lib/cache + command: ["gunicorn", "--bind", "0.0.0.0:5000", "-w", "4", "app:get_production_flask_app(\"/var/lib/cache\")"] + writer: + build: + context: . + volumes: + - cache-volume:/var/lib/cache + command: ["python", "app.py", "writer", "--cache-location", "/var/lib/cache"] + +volumes: + cache-volume: diff --git a/requirements.txt b/requirements.txt index 3853af5..9f49bed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ requests==2.26.0 urllib3==1.26.7 gunicorn==20.1.0 semantic-version==2.10.0 +Werkzeug==2.2.2