mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 14:04:20 +01:00
Add healthcheck endpoint and timed_lru_cache function (#2135)
* Add healthcheck endpoint and timed_lru_cache function
This commit is contained in:
34
CTFd/cache/__init__.py
vendored
34
CTFd/cache/__init__.py
vendored
@@ -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.
|
||||
|
||||
18
CTFd/utils/health/__init__.py
Normal file
18
CTFd/utils/health/__init__.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user