dirac

Dirac v1.7.2 is out: https://github.com/binaryage/dirac/releases/tag/v1.7.2
richiardiandrea 2017-06-26T00:34:31.728203Z

Yeah I need to specify that, you need 2.7.2-SNAPSHOT

richiardiandrea 2017-06-26T00:35:24.731899Z

to do that, create and/or edit boot.properties in the project folder and set:

#<http://boot-clj.com>
#Sat Dec 31 19:36:01 PST 2016
BOOT_CLOJURE_NAME=org.clojure/clojure
BOOT_CLOJURE_VERSION=1.8.0
BOOT_VERSION=2.7.2-SNAPSHOT

richiardiandrea 2017-06-26T00:58:28.826271Z

actually version 2.7.1 should be good

richiardiandrea 2017-06-26T02:21:55.238607Z

so yeah still some work to do

richiardiandrea 2017-06-26T02:26:16.259927Z

there should also be a working demo here: https://github.com/arichiardi/figreload-demo

2017-06-26T09:09:30.237403Z

@richiardiandrea just tried your figreload-demo and and got https://gist.github.com/darwin/3f3bdbdf0cb946abed76aeba6215e06e, so it seems that figwheel sidecar and nREPL server do not share same JVM

2017-06-26T09:09:53.242548Z

otherwise figwheel compiler state(s) would be listed in (dirac :ls)

2017-06-26T09:13:04.285064Z

btw. I don’t even see any mention of figwheel connection at localhost:3000, in console messages

2017-06-26T09:29:13.502771Z

I just briefly looked at boot-figreload and it does not look like you are using fighwheel sidecar on server side, you just grabbed a few utility functions to communicate with figwheel client, but the core logic of the sidecar is replaced by your own implementation

👍 1
2017-06-26T09:29:21.504732Z

this is not going to work I’m afraid

2017-06-26T09:29:42.509192Z

also I don’t see the specific point where you actually recompile modified cljs files

2017-06-26T09:32:05.542147Z

looking at deftask reload but was unable to find the place where the build actually occurs, is it done behind the scenes by some other task? maybe watch task?

2017-06-26T09:36:05.595415Z

so dirac would need access to compiler states of this cljs task, to work seamlessly with this setup. By seamlessly I mean “But there is a subtle problem. As you probably know traditionally you had to make effort to keep your REPL environment in-sync with your runtime environment being evolved by hot-reloading. Figwheel REPL has an advantage that it is using the same compiler environment as was used for last incremental compilation. That means that Figwheel REPL is always in sync and you don’t have to ‘load-file’ or somehow reload/refresh namespaces in your REPL.” as described here https://github.com/binaryage/dirac/blob/master/docs/about-repls.md#dirac--figwheel

2017-06-26T09:44:17.702572Z

btw. compiler management in dirac is implemented here: https://github.com/binaryage/dirac/blob/master/src/nrepl/dirac/nrepl/compilers.clj#L89-L94 when scanning for available compiler states, it first lists compilers for current nREPL session, then lists all compilers for other nREPL sessions (e.g. you have connected multiple dirac REPLs to your nREPL server each using a distinct nREPL session) and then it scans for figwheel presence and grabs compiler states from figwheel sidecar (again there may be multiple ones because figwheel sidecar keeps one compiler per build-id)

2017-06-26T09:45:11.714322Z

you would have to implement additional scanning for boot’s compilers managed by boot-cljs, I guess

2017-06-26T09:45:39.720377Z

and this might not be easily possible because boot task are isolated in pods and don’t share same JVM

richiardiandrea 2017-06-26T14:35:18.093802Z

Thanks, yes I started to suspect I was missing a piece. You are right I emulate figwheel's server side. I guess that when one executes a command in the nRepl with figwheel the same command is evaluated in the browser, otherwise I don't see how you can keep two compiler envs in sync...but I will investigate more... don't take my words now I have just woken up 😀

2017-06-26T14:36:27.120580Z

there are two independent operations, 1. compilation cljs->js 2. eval of js

2017-06-26T14:37:03.134768Z

both operations are stateful, #1 needs some compiler state (or empty one) #2 needs js runtime env (browser’s js context)

richiardiandrea 2017-06-26T14:38:50.176681Z

Compilation is handled by boot-cljs and the state is there, you are right it is in a pod...but that is rarely a problem with file reloading going on

2017-06-26T14:38:51.176854Z

ideally we would like to keep compiler’s state in nREPL server in sync with compilations happening because we want to hot-reload some code3

richiardiandrea 2017-06-26T14:39:49.199638Z

Yeah so in nrepl server I probably need to file reload as well 😀

richiardiandrea 2017-06-26T14:40:11.208212Z

Nobody has done it... Maybe it is not doable

2017-06-26T14:40:39.219003Z

well, ideally you want nREPL server to share compiler state with boot-cljs

2017-06-26T14:40:56.225303Z

in other words, you want all parts seeing and using the same compiler state

richiardiandrea 2017-06-26T14:41:33.239403Z

Yeah this at the moment as you were saying this is not possible in boot...

2017-06-26T14:41:34.239793Z

trying to reload files in nREPL could work for basic workflows, but I can imagine it would be pretty fragile

2017-06-26T14:42:20.257818Z

I’m not sure if it is not possible

2017-06-26T14:42:45.267403Z

I don’t know how pod isolation works and if boot-cljs coudn’t be run in the same JVM context as nREPL server

2017-06-26T14:42:54.270966Z

or maybe some comm channel could be estabilished

2017-06-26T14:43:27.284242Z

cljs from dirac’s nrepl middleware would be sent to boot-cljs process to be compiled and returned back as js

2017-06-26T14:43:40.289369Z

sounds as quite simple interop to me

2017-06-26T14:48:06.396613Z

or maybe vice-versa, nREPL server would manage compilers and expose some api and boot-cljs would use it for compilations

richiardiandrea 2017-06-26T14:48:11.398429Z

Yeah seems like a good compromise..will explore as this is something that I have not seen anywhere in boot and probably the normal repl does not do

2017-06-26T14:48:45.411649Z

yes, hot-reloading is not a common practice in Clojure world

2017-06-26T14:49:09.421323Z

so that is why nobody cares in clj REPL tooling

2017-06-26T14:49:47.436148Z

but with figwheel it is completely different game, I use hot-reloading to do live coding much more often than interacting with REPL

👍 1
2017-06-26T14:50:11.445838Z

clojure people have only REPL so they cannot get out-of-sync

richiardiandrea 2017-06-26T15:11:18.968277Z

So given what you say above we are still good, folks don't expect state to be in sync when using boot-cljs-repl either but they can now use dirac

richiardiandrea 2017-06-26T15:11:51.981375Z

Problem is when a file changes it will be hot reloaded

richiardiandrea 2017-06-26T15:12:13.990294Z

Potentially overriding stuff

2017-06-26T15:14:10.037351Z

simplest problematic case is that you def some new thing like a function, save file, it hot-reloads, updates js context, then go to Dirac REPL and expect that function to be known to compiler, but when you enter some cljs expression using that symbol name, cljs compiler in nREPL won’t be aware of it

2017-06-26T15:14:54.055572Z

you would first have to load-file it to refresh nREPL’s compiler state to match boot-cljs’s compiler state

2017-06-26T15:15:49.077987Z

but the general case is much more complicated, e.g. touching a macro which triggers a cascade of recompilations for dependent cljs code

2017-06-26T15:16:14.087646Z

at least figwheel deals with these cases well

richiardiandrea 2017-06-26T15:18:29.142871Z

Yeah it has been a good digging exercise to read Bruce's code

richiardiandrea 2017-06-26T15:22:33.243489Z

Compiler state is data, I wonder whether simple diffing would work

2017-06-26T15:23:25.265304Z

not sure, I’m afraid there might be some hard-to-serialize java stuff in there

2017-06-26T15:23:50.275437Z

btw. I wanted to switch to boot at least twice in the past, it has very nice functional design and vibrant community, but figwheel was always the show stopper

2017-06-26T15:23:51.275935Z

for me

richiardiandrea 2017-06-26T15:27:28.365399Z

Yeah I can understand that is why I have started porting it. I remember sitting with Fransisco Avila and Bruce at the Conj 2016 trying to untangle the thread

2017-06-26T15:27:57.377418Z

why you couldn’t reuse figwheel components directly?

richiardiandrea 2017-06-26T15:28:29.391136Z

Because Boot's filesystem is immutable

richiardiandrea 2017-06-26T15:28:53.400848Z

There is a task that uses it directly

richiardiandrea 2017-06-26T15:29:21.412327Z

But you cannot stay in the task world

richiardiandrea 2017-06-26T15:29:44.421353Z

You need to use an external tmp folder only for figwheel

2017-06-26T15:30:15.435113Z

awfully many hours were poured into figwheel’s impl I think, I would imagine that tmp folder isolation and some bridge in and out for interop with other boot tasks

richiardiandrea 2017-06-26T15:31:21.463656Z

Yes that was my idea, try to reuse as much as I can

2017-06-26T15:31:59.479417Z

nREPL server is also a side-effecting thing with its own direct file access and nobody reimplemented it completely in boot, I guess 🙂

richiardiandrea 2017-06-26T15:32:08.483096Z

In the meantime solving bugs and improving the HUD (Boot's HUD is not the same and it would evolve to copy figwheel's anyways)

richiardiandrea 2017-06-26T15:33:02.505075Z

Yeah no, the nRepl server is untouched. The folks in #unrepl are thinking about a rewrite though

2017-06-26T15:34:23.537915Z

ok, boot ecosystem is heathy, you will get to figwheel parity at some point I believe

2017-06-26T15:34:42.545185Z

but for now I’m sticking with lein, I guess

richiardiandrea 2017-06-26T15:36:43.593379Z

😀 btw this is what I discovered about the compiler state, and I did not notice anything unreadable, but I will ask: https://github.com/Lambda-X/replumb/blob/master/src/cljs/replumb/ast.cljs

2017-06-26T15:41:45.712261Z

not sure how replumb it related to this, but I would look here: https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/env.cljc#L25-L44

2017-06-26T15:42:46.736281Z

if I knew you were serializing the state to send it over some wire, I could be malicious and simply pass a custom compiler option which would be some unserializable thing, and you would be done

richiardiandrea 2017-06-26T15:43:00.741609Z

Yeah replumb is cljs-in-cljs layer I wrote

richiardiandrea 2017-06-26T15:43:19.748770Z

Ah ah ok, but this is only in dev mode

2017-06-26T15:43:56.763199Z

hmm, I don’t think so, this is compiler state for whatever mode

2017-06-26T15:44:54.785200Z

anytime in the future they might decide to put something unserializable there

richiardiandrea 2017-06-26T15:46:09.814552Z

I am not that sure, or cljs-in-cljs will break

richiardiandrea 2017-06-26T15:46:48.829727Z

And you don't want to break Lumo, Planck, ...

2017-06-26T15:47:00.834191Z

there could be two code paths, normal and bootstrapped

2017-06-26T15:47:10.837926Z

in theory, didn’t review it

richiardiandrea 2017-06-26T15:47:36.848777Z

if I remember correctly it is one

2017-06-26T15:47:42.850961Z

but you are correct that with bootstrapped it is unlikely to contain some wild stuff

1
richiardiandrea 2017-06-26T15:47:45.852330Z

I might be wrong though

2017-06-26T15:48:20.866146Z

but I gave you an example of breaking code already, with foreign :options