|
@@ -6,18 +6,22 @@
|
|
|
import os
|
|
|
import cherrypy
|
|
|
from threading import Thread
|
|
|
-from typing import Union
|
|
|
+from typing import Tuple, Union
|
|
|
from bottle import (
|
|
|
route, request, response,
|
|
|
static_file,
|
|
|
FormsDict,
|
|
|
)
|
|
|
+import cherrypy
|
|
|
from psycopg import Cursor, connect
|
|
|
from psycopg.rows import TupleRow
|
|
|
-from .route_decorators import normalize, poison, cursor
|
|
|
+from urllib.parse import parse_qs
|
|
|
+
|
|
|
+from .QueryCache import QueryCache
|
|
|
+from .route_decorators import cache, cursor
|
|
|
from .query_to_xml import get_categories, get_groups, get_products, get_tags
|
|
|
from .CachedLoadingPage import CachedLoadingPage
|
|
|
-from .Cache import Cache
|
|
|
+from .PageCache import PageCache
|
|
|
from . import trend as worker
|
|
|
|
|
|
host = f"host={os.getenv('HOST')}"
|
|
@@ -39,20 +43,37 @@ def trend_thread(conn, path, forms):
|
|
|
)).start()
|
|
|
return cb
|
|
|
|
|
|
+PAGE_CACHE = PageCache(10)
|
|
|
+QUERY_CACHE = QueryCache(None)
|
|
|
+
|
|
|
@route('/grocery/trend', method=['GET', 'POST'])
|
|
|
-@poison(cache=Cache(10))
|
|
|
-@normalize
|
|
|
-def trend(key: str, forms: FormsDict, cache: Cache):
|
|
|
+@cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
|
|
|
+def trend(key: Tuple[str, int], cache: PageCache):
|
|
|
_, _, path, *_ = request.urlparts
|
|
|
-
|
|
|
+ cherrypy.log(f"key={key}")
|
|
|
page = cache[key]
|
|
|
if page is None:
|
|
|
- page = cache.add(key, CachedLoadingPage([], trend_thread(conn, path, forms)))
|
|
|
+ form = key_to_form(key)
|
|
|
+ cherrypy.log(f"form={form}")
|
|
|
+ page = cache.add(key, CachedLoadingPage([], trend_thread(conn, path, form)))
|
|
|
|
|
|
for i in iter_page(page):
|
|
|
yield i
|
|
|
|
|
|
|
|
|
+def query_to_form(query):
|
|
|
+ form = FormsDict()
|
|
|
+ for k, v in parse_qs(query).items():
|
|
|
+ for item in v:
|
|
|
+ form.append(k, item)
|
|
|
+ return form
|
|
|
+
|
|
|
+
|
|
|
+def key_to_form(key):
|
|
|
+ query, _ = key
|
|
|
+ return query_to_form(query)
|
|
|
+
|
|
|
+
|
|
|
def iter_page(page):
|
|
|
|
|
|
resp = list(page.value)
|
|
@@ -72,36 +93,36 @@ def iter_page(page):
|
|
|
|
|
|
|
|
|
@route('/grocery/groups', method=['GET', 'POST'])
|
|
|
-@poison(cache=Cache(10))
|
|
|
-@normalize
|
|
|
+@cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
|
|
|
@cursor(connection=conn)
|
|
|
-def groups(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
+def groups(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
|
|
|
+ form = key_to_form(key)
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_groups(cur, forms)
|
|
|
+ return get_groups(cur, form)
|
|
|
|
|
|
|
|
|
@route('/grocery/categories', method=['GET', 'POST'])
|
|
|
-@poison(cache=Cache(10))
|
|
|
-@normalize
|
|
|
+@cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
|
|
|
@cursor(connection=conn)
|
|
|
-def categories(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
+def categories(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
|
|
|
+ form = key_to_form(key)
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_categories(cur, forms)
|
|
|
+ return get_categories(cur, form)
|
|
|
|
|
|
|
|
|
@route('/grocery/products', method=['GET', 'POST'])
|
|
|
-@poison(cache=Cache(10))
|
|
|
-@normalize
|
|
|
+@cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
|
|
|
@cursor(connection=conn)
|
|
|
-def products(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
+def products(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
|
|
|
+ form = key_to_form(key)
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_products(cur, forms)
|
|
|
+ return get_products(cur, form)
|
|
|
|
|
|
|
|
|
@route('/grocery/tags', method=['GET', 'POST'])
|
|
|
-@poison(cache=Cache(10))
|
|
|
-@normalize
|
|
|
+@cache(query_cache=QUERY_CACHE, page_cache=PAGE_CACHE)
|
|
|
@cursor(connection=conn)
|
|
|
-def tags(cur: Cursor[TupleRow], key: Union[int, str], forms: FormsDict, cache: Cache):
|
|
|
+def tags(cur: Cursor[TupleRow], key: Tuple[str, int], cache: PageCache):
|
|
|
+ form = key_to_form(key)
|
|
|
response.content_type = 'application/xhtml+xml; charset=utf-8'
|
|
|
- return get_tags(cur, forms)
|
|
|
+ return get_tags(cur, form)
|