Fork me on GitHub
#hyperfiddle
<
2023-06-29
>
Lidor Cohen09:06:36

Hello! 🙂 I'm trying to get rcf working in my shadow-cljs project: • I have this (and only this as regarding to rcf) in my shadow-cljs.edn under :dependencies: [com.hyperfiddle/rcf "20220926-202227"] • I have this dev file:

(ns dev.core
  (:require [spiritt.experiments.obj-tests]
            [portal.web :as po]
            [hyperfiddle.rcf :refer [tests]]))

  ; wait to enable tests until after app namespaces are loaded
(hyperfiddle.rcf/enable!)

  ; subsequent REPL interactions will run tests

  ; prevent test execution during cljs hot code reload
(defn ^:dev/before-load stop [] (hyperfiddle.rcf/enable! false))
(defn ^:dev/after-load start [] (hyperfiddle.rcf/enable!))


(comment
  (po/open)
  (add-tap po/submit)

    ;; 
  )
• And I have these tests:
(ns spiritt.experiments.obj-tests
  (:require ...
            [hyperfiddle.rcf :refer [tests]]))

(hyperfiddle.rcf/enable!)

.
.
.

(tests
 (get-slot spatial-method :b) := "TEST1 SUCC1"

.
.
.

;;   
 )

Lidor Cohen09:06:32

Now, I'm not sure what to expect, I'm trying evaluating tests and I get nil. Loading the file doesn't do anything. (I'm using vscode + calva BTW)

Dustin Getz10:06:02

check browser console

Lidor Cohen10:06:47

nothing... it should happen when I eval tests?

xificurC10:06:17

are these cljs files?

xificurC10:06:27

the cljs hooks you copied turn rcf off while the namespaces are loaded

xificurC10:06:03

to run them manually one needs to connect a cljs REPL and eval the tests blocks

Dustin Getz11:06:05

For CLJS tests to run, rcf/enable! must be true in both clj (macroexpansion time) and cljs (js runtime). Successful runs will print green checkboxes in the browser console; clojure REPLs don't intercept the async print properly

Lidor Cohen11:06:49

🙏 I'll give it a try

Lidor Cohen11:06:34

Got it to work 🥳

🎉 2
Lidor Cohen11:06:13

Will send here all that's needed for the simplest setup with cljs and shadow

🙏 2
Dustin Getz12:06:41

Appreciate that thank you, I'd like to understand what you were missing before

Lidor Cohen12:06:36

shadow build-hook:

:build-hooks [(dev.core/rcf-shadow-hook)]
hook itself clj file: (dev/core.clj)
(ns dev.core
  (:require [hyperfiddle.rcf]))

(def rcf-enable! (delay @(requiring-resolve 'hyperfiddle.rcf/enable!)))

(defn rcf-shadow-hook {:shadow.build/stages #{:compile-prepare :compile-finish}}
  [build-state & args]
;; NOTE this won't prevent RCF tests to run during :require-macros phase
  (case (:shadow.build/stage build-state)
    :compile-prepare (@rcf-enable! false)
    :compile-finish (@rcf-enable!))
  build-state)
cljs before-load & after-load
(defn ^:dev/after-load start []
  (js/console.log "Starting...")
  (hyperfiddle.rcf/enable!))

(defn ^:dev/before-load stop []
  (js/console.log "Stopping...")
  (hyperfiddle.rcf/enable! false))

Lidor Cohen12:06:59

I was missing the clj biuld-hook

Dustin Getz12:06:05

IIRC that is optional, are you saying it is necessary? I believe the purpose of the shadow hook is to prevent JVM tests from running during shadow reloads related to macro namespaces

Lidor Cohen12:06:25

I think it's what enables rcf in clj:

:compile-finish (@rcf-enable!)

Lidor Cohen12:06:38

but I'm far from sure

Dustin Getz12:06:59

ah, that line can be moved to an entry ns like dev.cljc

Lidor Cohen12:06:39

My project is exclusivly cljs (shadow) my entry is cljs file I'm not sure how to incorporate a cljc entry point...

😮 2
Lidor Cohen12:06:48

in shadow it was the build hook for me

Dustin Getz12:06:49

i just added that sentence to the readme fwiw

Lidor Cohen12:06:27

👍 it what helped me 🙂

Dustin Getz12:06:45

I ticked this, thanks

braai engineer13:06:10

Anyone have a mySQL Electric example lying around to refresh all viewers anytime anything changes?

Dustin Getz13:06:08

afaik mostly this has been hacks, nobody has done a real integration with a tx-notification-queue of some sort

Dustin Getz13:06:01

the typical hack is to wrap the transact call and increment a counter out of band to force refresh queries

braai engineer13:06:32

OK so hack is: central server-side counter and any time tx just increment counter. that will work fine for now 🙂

👍 2
Dustin Getz13:06:35

another easy approach is to refresh queries when the user navigates like its 2010

2
braai engineer16:06:38

I can see data/!counter being incremented on tx, but (data/query-geom ...) does not rerun. How do I force it to re-run when data/!counter changes?

(e/defn App []
  (e/client
    (let [cnt (e/server (e/watch data/!counter))]
      (dom/div
        (dom/text cnt "hi: " cnt " ok")
        (dom/pre
          (dom/text
            (e/server (pr-str (data/query-geom data/conn)))))))))

;; In data I (swap! !counter inc) on tx.

braai engineer16:06:19

Do I have to pass counter as an argument to my query function? e.g. (data/query-geom hacky-counter conn args ...) ?

Dustin Getz16:06:26

yes, expressions re-evaluate exactly when their arguments change

Dustin Getz16:06:00

you can wrap it if you want, ((fn [_] (query-geom conn)) cache-bust)

denik15:06:36

stuck trying to run code based on dom events. the goal is to run code inside an electric view every time the window is focused. eu/window-focus is a flow observing and yielding the focus event

denik15:06:08

basically looking for a (whenever <x (do y)) I know that one way is to pass x into the function inside the when expression. however, since the value is a js object and there’s a server boundary it does not serialize. I could write some more code to return a serializable value instead (e.g. (rand)) but wondering if there’s a more elegant/idiomatic approach

Dustin Getz16:06:18

the undocumented APIs https://github.com/hyperfiddle/electric/blob/1f683adc6552be0f3f41b90e86305c6270917265/src/hyperfiddle/electric.cljc#L447-L537 (that UI4 uses) is the current way to do this, the problem is that they are overcomplicated, we only released them because they fixed bugs in UI4

Dustin Getz16:06:09

They handle edge cases like, what happens if the window focus events are in rapid succession, faster than latency, and in the "event callback" there is an e/server. • Do you want to cancel and discard the previous callback and start over with the new value? use e/for-event-pending-switch • Do you want to run N callbacks concurrently? use e/for-event-pending • Do you want to backpressure the user, disabling the control to block them from submitting events so fast? e/do-event-pending

👀 2
Dustin Getz16:06:04

This over-complicated code is why UI5 uses a completely different pattern, no more callbacks at all, but we are not close to shipping it

👌 2