diff options
| author | unwox <me@unwox.com> | 2024-10-17 10:32:35 +0600 |
|---|---|---|
| committer | unwox <me@unwox.com> | 2024-10-17 10:53:30 +0600 |
| commit | ff8c6c9dde3a877b51e2fabafa579e2c05dc856e (patch) | |
| tree | 3b6c9d8638ee78f913540e25ac7fc17433b906b6 | |
| parent | 43c7b5de358e8a158e9ed3c396d3866845682515 (diff) | |
implement caching
| -rw-r--r-- | bin/fetch.fnl | 7 | ||||
| -rw-r--r-- | bin/serve.fnl | 71 | ||||
| -rw-r--r-- | lib/array.fnl | 12 | ||||
| -rw-r--r-- | lib/cache.fnl | 21 |
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} |
