Skip to content

Commit d99f05d

Browse files
committed
Remove cache implementation this is really an application concern
1 parent a753609 commit d99f05d

File tree

19 files changed

+136
-165
lines changed

19 files changed

+136
-165
lines changed

README.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,15 @@ The only way for actions to affect the view returned by the `render-fn` running
7777
- Actions modify the database and return a 204 or a 200 if they `patch-signals`.
7878
- Render functions re-render when the database changes and send an update down the updates SSE connection.
7979

80-
#### Work sharing (caching)
81-
82-
Work sharing is the term I'm using for sharing renders between connected users. This can be useful when a lot of connected users share the same view. For example a leader board, game board, presence indicator etc. It ensures the work (eg: query and html generation) for that view is only done once regardless of the number of connected users.
83-
84-
There's a lot of ways you can do this. I've settled on a simple cache that gets invalidate when a `:refresh-event` is fired. This means the cache is invalidated at most every X msec (determined by `:max-refresh-ms`) and only if the db state has changed.
80+
#### Batching
8581

86-
To add something to the cache wrap the function in the `cache` higher order function.
82+
Batching pairs really well with CQRS as you have a resolution window, this defines the maximum frequency the view can update, or in other terms the granularity/resolution of the view. Batching can generally be used to improve throughput by batching changes.
8783

88-
#### Batching
84+
#### Work sharing (caching)
8985

90-
Batching pairs really well with CQRS as you have a resolution window, this defines the maximum frequency the view can update, or in other terms the granularity/resolution of the view. Batching can generally be used to improve throughput by batching changes.
86+
Work sharing is the term I'm using for sharing renders between connected users. This can be useful when a lot of connected users share the same view. For example a leader board, game board, presence indicator etc. It ensures the work (eg: query and html generation) for that view is only done once regardless of the number of connected users.
9187

92-
However, there is one downsides with batching to keep in mind and that is you don't get atomic transactions. The transaction move to the batch level, not the transact/insert level. Transaction matter when you are dealing with constraints you want to deal with at the database level, classic example is accounting systems or ledgers where you want to be able to fail an atomic transaction that violates a constraint (like user balance going negative). The problem with batching is that that transaction constraint failure, fails the whole batch not only the transact that was culpable.
88+
The simplest way to do this is to recalculate and cache values after after a batch has been run.
9389

9490
#### Use `data-on-pointerdown/mous` over `data-on-click`
9591

examples/billion_cells/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
database-new.db*
1+
*.db*

examples/billion_cells/src/app/main.clj renamed to examples/billion_cells/src/billion_cells/main.clj

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(ns app.main
1+
(ns billion-cells.main
22
(:gen-class)
33
(:require [hyperlith.core :as h :refer [defaction defview]]
44
[hyperlith.extras.sqlite :as d]
@@ -358,7 +358,7 @@
358358
" and "
359359
[:a {:href "https://data-star.dev"} "Datastar"]
360360
" - "
361-
[:a {:href "https://github.com/andersmurphy/hyperlith/blob/master/examples/billion_cells/src/app/main.clj" } "source"]
361+
[:a {:href "https://github.com/andersmurphy/hyperlith/blob/master/examples/billion_cells/src/billion_cells/main.clj" } "source"]
362362
" - "
363363
[:a {:href "https://checkboxes.andersmurphy.com"} " more like this"]]])))
364364

@@ -401,7 +401,7 @@
401401

402402
(defn ctx-start []
403403
(let [{:keys [writer reader]}
404-
(d/init-db! "database-new.db"
404+
(d/init-db! (str *ns* ".db")
405405
{:pool-size 4
406406
:pragma {:foreign_keys false}})]
407407
;; Run migrations
@@ -427,25 +427,29 @@
427427
(.close (:db-write ctx))
428428
(.close (:db-read ctx)))
429429

430-
(defn -main [& _]
431-
(h/start-app
432-
{:max-refresh-ms 100
430+
(defonce app_ (atom nil))
431+
432+
(defn start-app [port]
433+
(reset! app_
434+
(h/start-app
435+
{:port port
436+
:max-refresh-ms 100
433437
:ctx-start ctx-start
434438
:ctx-stop ctx-stop
435-
:csrf-secret (h/env :csrf-secret)}))
439+
:csrf-secret (h/env :csrf-secret)})))
436440

437441
;; Refresh app when you re-eval file
438-
(h/refresh-all!)
442+
(h/refresh-all! )
439443

440444
(comment
441-
(do (-main) nil)
445+
(do (start-app 8080) nil)
442446
;; (clojure.java.browse/browse-url "http://localhost:8080/")
443447

444448

445449
;; stop server
446-
(((h/get-app) :stop))
450+
((@app_ :stop))
447451

448-
(def db (-> (h/get-app) :ctx :db))
452+
(def db (-> @app_ :ctx :db))
449453

450454

451455

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.db*
File renamed without changes.
File renamed without changes.

examples/billion_checkboxes_blob/src/app/main.clj renamed to examples/billion_checkboxes/src/billion_checkboxes/main.clj

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(ns app.main
1+
(ns billion-checkboxes.main
22
(:gen-class)
33
(:require [hyperlith.core :as h :refer [defaction defview]]
44
[hyperlith.extras.sqlite :as d]
@@ -351,7 +351,7 @@
351351
" and "
352352
[:a {:href "https://data-star.dev"} "Datastar"]
353353
" - "
354-
[:a {:href "https://github.com/andersmurphy/hyperlith/blob/master/examples/billion_checkboxes_blob/src/app/main.clj" } "source"]
354+
[:a {:href "https://github.com/andersmurphy/hyperlith/blob/master/examples/billion_checkboxes/src/billion_checkboxes/main.clj" } "source"]
355355
" - "
356356
[:a {:href "https://cells.andersmurphy.com"} " more like this"]]])))
357357

@@ -389,7 +389,7 @@
389389

390390
(defn ctx-start []
391391
(let [{:keys [writer reader]}
392-
(d/init-db! "database-new.db"
392+
(d/init-db! (str *ns* ".db")
393393
{:pool-size 4
394394
:pragma {:foreign_keys false}})]
395395
;; Run migrations
@@ -416,30 +416,34 @@
416416
(.close (:db-write ctx))
417417
(.close (:db-read ctx)))
418418

419-
(defn -main [& _]
420-
(h/start-app
421-
{:max-refresh-ms 100
422-
:ctx-start ctx-start
423-
:ctx-stop ctx-stop
424-
:csrf-secret (h/env :csrf-secret)}))
419+
(defonce app_ (atom nil))
420+
421+
(defn start-app [port]
422+
(reset! app_
423+
(h/start-app
424+
{:port port
425+
:max-refresh-ms 100
426+
:ctx-start ctx-start
427+
:ctx-stop ctx-stop
428+
:csrf-secret (h/env :csrf-secret)})))
425429

426430
;; Refresh app when you re-eval file
427431
(h/refresh-all!)
428432

429433
(comment
430-
(do (-main) nil)
434+
(do (start-app 8080) nil)
431435
;; (clojure.java.browse/browse-url "http://localhost:8080/")
432-
436+
433437

434438
;; stop server
435-
(((h/get-app) :stop))
439+
((@app_ :stop))
436440

437-
(def db (-> (h/get-app) :ctx :db))
441+
(def db (-> @app_ :ctx :db))
438442

439443
,)
440444

441445
(comment
442-
(def db (-> (h/get-app) :ctx :db))
446+
(def db (-> @app_ :ctx :db))
443447
(d/pragma-check db)
444448

445449
;; Execution time mean : 148.516131 ms
@@ -475,11 +479,11 @@
475479
(d/q db
476480
["SELECT chunk_id, JSON_GROUP_ARRAY(state) AS chunk_cells FROM cell WHERE chunk_id IN (?, ?, ?, ?, ?, ?, ?, ?, ?) GROUP BY chunk_id" 1978 3955 5932 1979 3956 5933 1980 3957 5934]))
477481

478-
(def tab-state (-> (h/get-app) :ctx :tab))
482+
(def tab-state (-> @app_ :ctx :tab))
479483

480484
(count @tab-state)
481485

482-
(def db-write (-> (h/get-app) :ctx :db-write))
486+
(def db-write (-> @app_ :ctx :db-write))
483487

484488
(d/q db-write
485489
{:update :chunk
@@ -504,15 +508,15 @@
504508
)
505509

506510
(comment
507-
(def wraped-router (-> (h/get-app) :wraped-router))
511+
(def wrapped-router (-> @app_ :wrapped-router))
508512

509513
(future
510514
(time
511515
(run!
512516
(fn [_]
513517
(run!
514518
(fn [_]
515-
(wraped-router
519+
(wrapped-router
516520
{:headers
517521
{"accept-encoding" "br"
518522
"cookie" "__Host-sid=5SNfeDa90PhXl0expOLFGdjtrpY; __Host-csrf=3UsG62ic9wLsg9EVQhGupw"

examples/chat_atom/src/app/main.clj

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@
2929
(defn get-messages [db]
3030
(reverse (@db :messages)))
3131

32-
(def messages
33-
(h/cache
34-
(fn [db]
35-
(for [[id content] (get-messages db)]
36-
[:p {:id id} content]))))
32+
(defn messages [db]
33+
(for [[id content] (get-messages db)]
34+
[:p {:id id} content]))
3735

3836
(defaction handler-send-message [{:keys [_sid db] {:keys [message]} :body}]
3937
(when-not (str/blank? message)
@@ -76,12 +74,12 @@
7674
(h/refresh-all!)
7775

7876
(comment
79-
(-main)
77+
(def app (-main))
8078
;; (clojure.java.browse/browse-url "http://localhost:8080/")
8179

8280
;; stop server
83-
(((h/get-app) :stop))
81+
((app :stop))
8482

8583
;; query outside of handler
86-
(get-messages (-> (h/get-app) :ctx :db))
84+
(get-messages (-> app :ctx :db))
8785
,)

examples/communtative_connected_count/src/app/main.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@
6464
(h/refresh-all!)
6565

6666
(comment
67-
(-main)
67+
(def app (-main))
6868
;; (clojure.java.browse/browse-url "http://localhost:8080/")
6969

7070
;; stop server
71-
(((h/get-app) :stop))
71+
((app :stop))
7272

7373

7474
,)

0 commit comments

Comments
 (0)