summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunwox <me@unwox.com>2024-10-17 10:32:35 +0600
committerunwox <me@unwox.com>2024-10-17 10:53:30 +0600
commitff8c6c9dde3a877b51e2fabafa579e2c05dc856e (patch)
tree3b6c9d8638ee78f913540e25ac7fc17433b906b6
parent43c7b5de358e8a158e9ed3c396d3866845682515 (diff)
implement caching
-rw-r--r--bin/fetch.fnl7
-rw-r--r--bin/serve.fnl71
-rw-r--r--lib/array.fnl12
-rw-r--r--lib/cache.fnl21
4 files changed, 79 insertions, 32 deletions
diff --git a/bin/fetch.fnl b/bin/fetch.fnl
index 3ef57df..da5383d 100644
--- a/bin/fetch.fnl
+++ b/bin/fetch.fnl
@@ -5,6 +5,7 @@
(local fennel (require :vendor.fennel))
(local array (require :lib.array))
+(local cache (require :lib.cache))
(local ozchai (require :parser.ozchai))
(local ipuer (require :parser.ipuer))
(local artoftea (require :parser.artoftea))
@@ -45,6 +46,11 @@
CREATE TABLE IF NOT EXISTS tags(
title TEXT NOT NULL PRIMARY KEY,
creation_time DATETIME NOT NULL
+ );
+
+ CREATE TABLE IF NOT EXISTS cache(
+ key TEXT NOT NULL PRIMARY KEY,
+ value TEXT
);" []))
(fn now []
@@ -138,6 +144,7 @@
ipuer.products
ozchai.products])]
(store-products tx (products)))
+(cache.clear-tx tx)
(must (luna.db.commit tx))
(populate-search-table)
diff --git a/bin/serve.fnl b/bin/serve.fnl
index 62e3962..e574238 100644
--- a/bin/serve.fnl
+++ b/bin/serve.fnl
@@ -11,6 +11,7 @@
(local str (require :lib.string))
(local texts (require :texts))
(local spellfix (require :spellfix))
+(local cache (require :lib.cache))
(local {: must : measure} (require :lib.utils))
(local ozchai (require :parser.ozchai))
@@ -65,6 +66,12 @@
(tonumber (. query key 1))
nil))
+(fn serialize-query [query]
+ (local flattened-object
+ (collect [k v (pairs query)]
+ (values k (array.join (map (fn [_ vv] (.. k "=" vv)) v) "&"))))
+ (array.join (array.list flattened-object) "&"))
+
(fn collect-form [params category]
{:query (str.trim (or (get-query-string params "query") ""))
:tags (filter #(~= "" $2) (or params.tags [category]))
@@ -365,40 +372,42 @@
[:footer {} paginator]]]]]])
(fn root-handler [{: path : query}]
- (fn respond [query category]
- (let [headers {:content-type "text/html"}
- page (or (get-query-number query "page") 1)
- form (collect-form query category)
- {: results : total}
- (if (not (form-empty? form))
- (measure "query products" #(query-products form page))
- {:total 48 :results (measure "random products" #(random-products 48))})]
- (values
- 200 headers
- (.. "<!DOCTYPE html>\n"
- (measure "render"
- #(html.render
- (base-template form page total results)
- true))))))
-
- (match (str.split path "/")
- ["red-tea"] (respond query "Красный чай")
- ["sheng-puer"] (respond query "Шен пуэр")
- ["shou-puer"] (respond query "Шу пуэр")
- ["oolong"] (respond query "Улун")
- ["green-tea"] (respond query "Зеленый чай")
- ["white-tea"] (respond query "Белый чай")
- ["yellow-tea"] (respond query "Желтый чай")
- ["teaware"] (respond query "Посуда")
- [] (respond query)
- _ (values 404 {} "not found")))
+ (local cache-key (.. path "?" (serialize-query query)))
+ (local cached (cache.get db cache-key))
+ (if cached
+ (values 200 {:content-type "text/html"} cached)
+ (do
+ (fn respond [query category]
+ (let [headers {:content-type "text/html"}
+ page (or (get-query-number query "page") 1)
+ form (collect-form query category)
+ {: results : total}
+ (if (not (form-empty? form))
+ (query-products form page)
+ {:total 48 :results (random-products 48)})]
+ (values
+ 200 headers
+ (cache.set db cache-key
+ (.. "<!DOCTYPE html>\n"
+ (html.render
+ (base-template form page total results)
+ true))))))
+
+ (match (str.split path "/")
+ ["red-tea"] (respond query "Красный чай")
+ ["sheng-puer"] (respond query "Шен пуэр")
+ ["shou-puer"] (respond query "Шу пуэр")
+ ["oolong"] (respond query "Улун")
+ ["green-tea"] (respond query "Зеленый чай")
+ ["white-tea"] (respond query "Белый чай")
+ ["yellow-tea"] (respond query "Желтый чай")
+ ["teaware"] (respond query "Посуда")
+ [] (respond query)
+ _ (values 404 {} "not found")))))
(fn robots-handler []
(values 200 {:content-type "text/plain"} "User-agent: *\nAllow: /"))
-(must (luna.router.route
- "GET /"
- (fn [req]
- (measure "root handler" #(root-handler req)))))
+(must (luna.router.route "GET /" root-handler))
(must (luna.router.route "GET /robots.txt" robots-handler))
(must (luna.router.static "GET /static/" "static/"))
diff --git a/lib/array.fnl b/lib/array.fnl
index 8b81c5c..8af6244 100644
--- a/lib/array.fnl
+++ b/lib/array.fnl
@@ -53,6 +53,16 @@
(lua "return true")))
false)
+(fn list [obj]
+ (local result [])
+ (var cursor 1)
+ (each [_ v (pairs obj)]
+ (tset result cursor v)
+ (set cursor (+ 1 cursor)))
+ ;; sort so we always return the same list for the same object
+ (table.sort result)
+ result)
+
(local join table.concat)
-{: sort : concat : diff : unique : flatten : join : contains}
+{: sort : concat : diff : unique : flatten : join : contains : list}
diff --git a/lib/cache.fnl b/lib/cache.fnl
new file mode 100644
index 0000000..b21a05e
--- /dev/null
+++ b/lib/cache.fnl
@@ -0,0 +1,21 @@
+(local {: must} (require :lib.utils))
+
+(fn get [db key else]
+ (local result
+ (must (luna.db.query db "SELECT value FROM cache WHERE key = ?"
+ [key])))
+ (or (if (and result (< 0 (# result)))
+ (. (. result 1) 1)
+ nil)
+ else))
+
+(fn _set [db key value]
+ value
+ (must (luna.db.exec db "INSERT OR REPLACE INTO cache VALUES (?, ?)"
+ [key value]))
+ value)
+
+(fn clear-tx [tx]
+ (must (luna.db.exec-tx tx "DELETE FROM cache" [])))
+
+{: get :set _set : clear-tx}