Skip to content

Commit

Permalink
PoC with response caching
Browse files Browse the repository at this point in the history
  • Loading branch information
lwesterhof committed Oct 25, 2024
1 parent 609dd99 commit dfe02cd
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 4 deletions.
8 changes: 8 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from admin.admin import admin_bp, set_theme_loader
from api import api_bp
from cache_config import cache
from datarequest.datarequest import datarequest_bp
from deposit.deposit import deposit_bp
from fileviewer.fileviewer import fileviewer_bp
Expand Down Expand Up @@ -128,6 +129,9 @@ def load_admin_setting() -> Dict[str, Any]:
# Start Flask-Session
Session(app)

# Initialize the cache.
cache.init_app(app)

# Start monitoring thread for extracting tech support information
# Monitor signal file can be set to empty to completely disable monitor thread
monitor_enabled: bool = app.config.get("MONITOR_SIGNAL_FILE", "/var/www/yoda/show-tech.sig") != ""
Expand Down Expand Up @@ -192,6 +196,10 @@ def static_loader() -> Optional[Response]:
return None


def authenticated() -> bool:
return g.get('user') is not None and g.get('irods') is not None


@app.before_request
def protect_pages() -> Optional[Response]:
"""Restricted pages access protection."""
Expand Down
33 changes: 33 additions & 0 deletions cache_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3

__copyright__ = 'Copyright (c) 2024, Utrecht University'
__license__ = 'GPLv3, see LICENSE'

from typing import Any, Dict, Optional

from flask import g, request, session
from flask_caching import Cache

config = {
'CACHE_TYPE': 'FileSystemCache',
'CACHE_DIR': '/tmp',
'CACHE_DEFAULT_TIMEOUT': 300
}


def authenticated() -> bool:
return g.get('user') is not None and g.get('irods') is not None


def make_key(key: Optional[str] = None) -> str:
if key is None:
key = f"{request.endpoint}_{request.method}"

if authenticated():
return f"{session.sid}-{key}"
else:
return f"unauthenticated-{key}"


# Create a Cache instance.
cache = Cache(config=config)
3 changes: 3 additions & 0 deletions general/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
from flask import Blueprint, redirect, render_template, Response, url_for
from flask_wtf.csrf import CSRFError

from cache_config import cache, make_key

general_bp = Blueprint('general_bp', __name__,
template_folder='templates/general',
static_folder='static/general',
static_url_path='/assets')


@general_bp.route('/')
@cache.cached(make_cache_key=make_key)
def index() -> Response:
return render_template('index.html')

Expand Down
3 changes: 3 additions & 0 deletions group_manager/group_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from flask import Blueprint, make_response, render_template, request, Response

import api
from cache_config import cache, make_key

group_manager_bp = Blueprint('group_manager_bp', __name__,
template_folder='templates',
Expand All @@ -14,6 +15,7 @@


@group_manager_bp.route('/')
@cache.cached(make_cache_key=make_key)
def index() -> Response:
response = api.call('group_data', data={})
group_hierarchy = response['data']['group_hierarchy']
Expand Down Expand Up @@ -67,6 +69,7 @@ def get_subcategories() -> Response:


@group_manager_bp.route('/get_schemas', methods=['POST'])
@cache.cached(make_cache_key=make_key)
def get_schemas() -> Response:
response = api.call('schema_get_schemas', data={})

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ python-irodsclient==2.2.0
Flask==3.0.2
flask-session==0.6.0
Flask-WTF==1.2.1
Flask-Caching==2.3.0
mod-wsgi==5.0.0
pyjwt[crypto]==2.8.0
requests==2.32.0
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import-order-style=smarkets
strictness=short
docstring_style=sphinx
max-line-length=127
application-import-names=admin,api,connman,errors,fileviewer,general,group_manager,monitor,research,search,open_search,stats,user,vault,deposit,intake,datarequest,util
application-import-names=admin,api,cache_config,connman,errors,fileviewer,general,group_manager,monitor,research,search,open_search,stats,user,vault,deposit,intake,datarequest,util
exclude=venv

[mypy]
Expand Down
3 changes: 3 additions & 0 deletions stats/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from flask import Blueprint, make_response, render_template, Response

import api
from cache_config import cache, make_key

stats_bp = Blueprint('stats_bp', __name__,
template_folder='templates',
Expand All @@ -14,6 +15,7 @@


@stats_bp.route('/')
@cache.cached(make_cache_key=make_key)
def index() -> Response:
# resource_tiers_response = api.call('resource_resource_and_tier_data', data={})
category_response = api.call('resource_category_stats', data={})
Expand All @@ -24,6 +26,7 @@ def index() -> Response:


@stats_bp.route('/export')
@cache.cached(make_cache_key=make_key)
def export() -> Response:
response = api.call('resource_monthly_category_stats', data={})

Expand Down
11 changes: 8 additions & 3 deletions user/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import api
import connman
from cache_config import cache, make_key
from util import is_email_in_domains, is_relative_url, log_error

# Blueprint creation
Expand Down Expand Up @@ -481,9 +482,13 @@ def prepare_user() -> None:
try:
endpoints = ["static", "call", "upload_get", "upload_post"]
if request.endpoint is not None and not request.endpoint.endswith(tuple(endpoints)):
# Check for notifications.
response = api.call('notifications_load', data={})
g.notifications = len(response['data'])
# Check for notifications (cached for 60 seconds).
response = cache.get(make_key('notifications_load'))
if response is None:
response = api.call('notifications_load', data={})
cache.set(make_key('notifications_load'), response, timeout=60)
else:
g.notifications = len(response['data'])

# Load saved settings.
if session.get('settings', None) is None:
Expand Down

0 comments on commit dfe02cd

Please sign in to comment.