Add healthcheck endpoint and timed_lru_cache function (#2135)

* Add healthcheck endpoint and timed_lru_cache function
This commit is contained in:
Kevin Chung
2022-06-16 14:39:47 -04:00
committed by GitHub
parent 0ab5dd4dfc
commit f1cc09767f
3 changed files with 62 additions and 0 deletions

View File

@@ -1,9 +1,43 @@
from functools import lru_cache, wraps
from time import monotonic_ns
from flask import request
from flask_caching import Cache, make_template_fragment_key
cache = Cache()
def timed_lru_cache(timeout: int = 300, maxsize: int = 64, typed: bool = False):
"""
lru_cache implementation that includes a time based expiry
Parameters:
seconds (int): Timeout in seconds to clear the WHOLE cache, default = 5 minutes
maxsize (int): Maximum Size of the Cache
typed (bool): Same value of different type will be a different entry
Implmentation from https://gist.github.com/Morreski/c1d08a3afa4040815eafd3891e16b945?permalink_comment_id=3437689#gistcomment-3437689
"""
def wrapper_cache(func):
func = lru_cache(maxsize=maxsize, typed=typed)(func)
func.delta = timeout * 10 ** 9
func.expiration = monotonic_ns() + func.delta
@wraps(func)
def wrapped_func(*args, **kwargs):
if monotonic_ns() >= func.expiration:
func.cache_clear()
func.expiration = monotonic_ns() + func.delta
return func(*args, **kwargs)
wrapped_func.cache_info = func.cache_info
wrapped_func.cache_clear = func.cache_clear
return wrapped_func
return wrapper_cache
def make_cache_key(path=None, key_prefix="view/%s"):
"""
This function mostly emulates Flask-Caching's `make_cache_key` function so we can delete cached api responses.

View File

@@ -0,0 +1,18 @@
from time import monotonic_ns
from flask import current_app
from sqlalchemy_utils import database_exists
from CTFd.cache import cache, timed_lru_cache
@timed_lru_cache(timeout=30)
def check_database():
return database_exists(current_app.config["SQLALCHEMY_DATABASE_URI"])
@timed_lru_cache(timeout=30)
def check_config():
value = monotonic_ns()
cache.set("healthcheck", value)
return cache.get("healthcheck") == value

View File

@@ -44,6 +44,7 @@ from CTFd.utils.email import (
DEFAULT_VERIFICATION_EMAIL_BODY,
DEFAULT_VERIFICATION_EMAIL_SUBJECT,
)
from CTFd.utils.health import check_config, check_database
from CTFd.utils.helpers import get_errors, get_infos, markup
from CTFd.utils.modes import USERS_MODE
from CTFd.utils.security.auth import login_user
@@ -504,3 +505,12 @@ def themes_beta(theme, path):
if os.path.isfile(cand_path):
return send_file(cand_path)
abort(404)
@views.route("/healthcheck")
def healthcheck():
if check_database() is False:
return "ERR", 500
if check_config() is False:
return "ERR", 500
return "OK", 200