lru cache for formatted answers (fixes #346)

This commit is contained in:
Igor Chubin 2019-09-07 15:12:10 +02:00
parent e78e6e6f22
commit de1b79d705
3 changed files with 66 additions and 4 deletions

50
lib/cache.py Normal file
View file

@ -0,0 +1,50 @@
"""
LRU-Cache implementation for formatted (`format=`) answers
"""
import datetime
import re
import time
import pylru
import pytz
CACHE_SIZE = 10000
CACHE = pylru.lrucache(CACHE_SIZE)
def _update_answer(answer):
def _now_in_tz(timezone):
return datetime.datetime.now(pytz.timezone(timezone)).strftime("%H:%M:%S%z")
if "%{{NOW(" in answer:
answer = re.sub(r"%{{NOW\(([^}]*)\)}}", lambda x: _now_in_tz(x.group(1)), answer)
return answer
def get_signature(user_agent, query_string, client_ip_address, lang):
"""
Get cache signature based on `user_agent`, `url_string`,
`lang`, and `client_ip_address`
"""
timestamp = int(time.time()) / 1000
signature = "%s:%s:%s:%s:%s" % \
(user_agent, query_string, client_ip_address, lang, timestamp)
return signature
def get(signature):
"""
If `update_answer` is not True, return answer as it is
stored in the cache. Otherwise update it, using
the `_update_answer` function.
"""
if signature in CACHE:
return _update_answer(CACHE[signature])
return None
def store(signature, value):
"""
Store in cache `value` for `signature`
"""
CACHE[signature] = value
return _update_answer(value)

View file

@ -481,13 +481,12 @@ def textual_information(data_parsed, geo_data, config):
output.append('Timezone: %s' % timezone) output.append('Timezone: %s' % timezone)
tmp_output = [] tmp_output = []
tmp_output.append(' Now: %s' tmp_output.append(' Now: %%{{NOW(%s)}}' % timezone)
% datetime.datetime.now(pytz.timezone(timezone)).strftime("%H:%M:%S%z"))
tmp_output.append('Dawn: %s' tmp_output.append('Dawn: %s'
% str(sun['dawn'].strftime("%H:%M:%S"))) % str(sun['dawn'].strftime("%H:%M:%S")))
tmp_output.append('Sunrise: %s' tmp_output.append('Sunrise: %s'
% str(sun['sunrise'].strftime("%H:%M:%S"))) % str(sun['sunrise'].strftime("%H:%M:%S")))
tmp_output.append(' Noon: %s' tmp_output.append(' Zenith: %s'
% str(sun['noon'].strftime("%H:%M:%S "))) % str(sun['noon'].strftime("%H:%M:%S ")))
tmp_output.append('Sunset: %s' tmp_output.append('Sunset: %s'
% str(sun['sunset'].strftime("%H:%M:%S"))) % str(sun['sunset'].strftime("%H:%M:%S")))

View file

@ -25,6 +25,8 @@ from limits import Limits
from wttr import get_wetter, get_moon from wttr import get_wetter, get_moon
from wttr_line import wttr_line from wttr_line import wttr_line
import cache
if not os.path.exists(os.path.dirname(LOG_FILE)): if not os.path.exists(os.path.dirname(LOG_FILE)):
os.makedirs(os.path.dirname(LOG_FILE)) os.makedirs(os.path.dirname(LOG_FILE))
logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG, format='%(asctime)s %(message)s') logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG, format='%(asctime)s %(message)s')
@ -211,6 +213,12 @@ def wttr(location, request):
html_output = get_output_format(request, query) html_output = get_output_format(request, query)
user_agent = request.headers.get('User-Agent', '').lower() user_agent = request.headers.get('User-Agent', '').lower()
# generating cache signature
cache_signature = cache.get_signature(user_agent, request.url, ip_addr, lang)
answer = cache.get(cache_signature)
if answer:
return _wrap_response(answer, html_output)
if location in PLAIN_TEXT_PAGES: if location in PLAIN_TEXT_PAGES:
help_ = show_text_file(location, lang) help_ = show_text_file(location, lang)
if html_output: if html_output:
@ -242,8 +250,13 @@ def wttr(location, request):
# We are ready to return the answer # We are ready to return the answer
try: try:
if fmt or 'format' in query: if fmt or 'format' in query:
response_text = wttr_line(
location, override_location_name, full_address, query, lang, fmt)
fmt = fmt or query.get('format')
response_text = cache.store(cache_signature, response_text)
return _wrap_response( return _wrap_response(
wttr_line(location, override_location_name, full_address, query, lang, fmt), response_text,
html_output) html_output)
if png_filename: if png_filename: