Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/production ready build #26

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
60 changes: 56 additions & 4 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import json
import subprocess
import semantic_version
import argparse

app = Flask(__name__)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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()
18 changes: 18 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -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:
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading