This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-05-10
Channels
- # aws (39)
- # babashka (4)
- # beginners (5)
- # biff (25)
- # cider (14)
- # clj-on-windows (40)
- # clojure-europe (36)
- # clojure-gamedev (1)
- # clojure-losangeles (4)
- # clojure-norway (51)
- # clojure-spec (5)
- # clojure-uk (2)
- # clojurescript (2)
- # clr (176)
- # data-science (10)
- # datalevin (17)
- # datomic (7)
- # deps-new (4)
- # docs (3)
- # emacs (12)
- # figwheel (3)
- # figwheel-main (5)
- # hyperfiddle (20)
- # instaparse (3)
- # introduce-yourself (8)
- # lsp (66)
- # malli (43)
- # off-topic (4)
- # rdf (11)
- # reagent (5)
- # releases (2)
- # sci (11)
- # shadow-cljs (24)
- # slack-help (2)
- # specter (7)
- # tools-deps (3)
- # xtdb (48)
I have a question about the startup of an electric program during development. Where is the compiled electric program injected into the ring middleware stack? What I found out from the sources:
start fn user(.clj)/main .
main loads shadow and later starts the server.
shadow compiles cljs from entry user(.cljs)/start.
start calls electric-boot.
because electric functions are macros, they are compiled and because clj and shadow use the same Repl the compiled electric program is available in clj.
and from here: how does it get into the ring stack?.
I like electric, but at the moment it feels a little magic. Of course it is not and I would like to understand, what is happening there :)search for “jetty” we have an example jetty server which hosts the websocket, each websocket gets an instance of the server DAG
Thanks for your answer. ok there is electric-ws-message-handler
and electric-ws-message-handler
. I looked into the hyperfiddle source code, but I am not able to figure out how the DAG is arriving there. Is there a def dag (atom)
or def ^dynamic dag
or how is this achieved? Maybe I am just blind and missing some simple statement?
Today IIRC the clojurescript build is responsible for both server and client • the client is compiled all the way down: Electric -> DAG IR -> CLJS -> JS • the server is compiled by the clojurescript build Electric -> DAG IR, and the server DAG value (IR, think bytecode) is embedded into the javascript artifact. The browser client will bootstrap the server by sending up the DAG value to the server in the first frame of the websocket, and then the server interprets the DAG IR at runtime. (Yes, that means the Electric frontend is compiled all the way to JS but the Electric backend is only partially compiled and then interpreted) There may be minor errors in this explanation but this is the gist of it. We have a branch that bakes the server DAG into the java artifact rather than bootstrapping from the client, i forget our exact plans for this but there will be changes this summer
Cool 🙂 Thanks for this explanation. This answers why I could not find anything. I have one more question. If the DAG is provided by the frontend to the server, would n’t this be a security issue or at least an entry point to a DOS attack? I mean, how does the server check, that the DAG is not manipulated?
As I said, this summer this is all getting rewritten, the current strategy is convenient for hot code reloading etc. In the meantime we can help you assert the hash in prod if you think this is a credible attack vector and you are using Electric for something serious.
Currently I am using it on a small hobby project to explore and learn about electric. I only use libraries in production, which I understand and where I have a sense for the implications of using x or y. I am not at the point yet, where I understand the electric system and its implications well enough to use it for production. However, I see the potential of electric and your answers on this channel already helped me a lot to get a better understanding of electric. So thanks again for answering my questions 🙂
hyperfiddle.electric-ui4/date
seems to throw when pressing the “Clear” button in browser’s native date picker (using Brave) because it tries to parse NaN:
core.cljs:200 "date input:" #inst "0NaN-NaN-NaNTNaN:NaN:NaN.NaN-00:00"
12:24:34.349 user.cljs:21 Reactor failure: cljs$core$ExceptionInfo {message: 'Remote error - 1011 java.lang.NumberFormatException: For input string: "NaN"',
e.g.:
(ui/date date-query (e/fn [v]
(prn "date input:" v)
(if (string/blank? v)
(reset! !date nil)
(reset! !date v)))
(dom/props {:placeholder "Date"}))
Fell back to dom/input.I ticketed it, you can probably easily PR this if urgent
thx, not urgent
When I run, e.g. XTDB_ENABLE_BYTEUTILS_SHA1=true clj -A:dev -X user/main
, there's this printout shadow-cljs - nREPL server started on port 9001
. I assume that's the normal JavaScript browser REPL, correct? If so, how are people getting a REPL up for the JVM (i.e. so they can run one of the comment forms)?
it is a JVM nrepl
you can also jack in from your editor in the usual way to get a REPL and run shadow from inside that, like here: https://github.com/hyperfiddle/electric-starter-app/blob/main/src/user.clj
use :dev alias
Okay, thanks, got it working. I needed to execute (def db (xt/db !xtdb))
in the user
namespace before the comment forms in app.todo-list
would work.
Feel free to PR if you want to improve something
One thing that's weird is I initially got the todos I had added in the browser client (there were two), but after adding a third, re-running the same query in the REPL returned the previous results (browser shows three).
Even weirder, running queries in user
return no items.
did you refresh the db val?