unrepl

discussing specification of an edn-based repl and its implementations.
cgrand 2017-04-07T09:06:22.777885Z

@pesterhazy I haven’t merged your PR yet because I’d like to discuss what happens when stdin is closed and how to control that.

cgrand 2017-04-07T09:07:51.798781Z

Currently I thought about :bye actions in the context of an upgrade (see https://github.com/cgrand/unrepl/blob/master/README.md#bye-actions)

cgrand 2017-04-07T09:08:14.803930Z

here it’s a bit different, similar to receiving a SIGHUP

pesterhazy 2017-04-07T09:10:47.840618Z

yeah that's why I initially gave it another name, :fin

pesterhazy 2017-04-07T09:13:36.879831Z

honestly not sure what the intended use for upgrading is

pesterhazy 2017-04-07T09:14:02.885710Z

my focus was to tackle the practical issue of knowing when the EDN stream ends

pesterhazy 2017-04-07T09:14:29.891851Z

what else would you want to happen if *in* is closed?

cgrand 2017-04-07T09:18:04.942274Z

If you have sent a future which prints or logs and *in* is closed then the future dies on the next print/log

cgrand 2017-04-07T09:19:14.957952Z

Should this be the default behaviour? If no what else?

pesterhazy 2017-04-07T09:20:12.971132Z

good point

pesterhazy 2017-04-07T09:20:24.974435Z

what else could we do?

pesterhazy 2017-04-07T09:20:40.978207Z

if the client disconnects, there's nowhere to write to

cgrand 2017-04-07T09:21:09.984499Z

/dev/null ?

cgrand 2017-04-07T09:21:29.989195Z

log files

pesterhazy 2017-04-07T09:23:47.019660Z

true

cgrand 2017-04-07T09:24:36.031060Z

maybe [:bye {:reason :disconnected :actions {:recapture-outs (....)}}]

pesterhazy 2017-04-07T09:25:26.042773Z

how does it work with nREPL?

cgrand 2017-04-07T09:25:51.048342Z

and everything goes to /dev/null until the :recapture-outs action form is issued somewhere

pesterhazy 2017-04-07T09:25:57.049896Z

if you (future (do (Thread/sleep 1000) (println :foo))) and disconnect

cgrand 2017-04-07T09:29:46.103543Z

so I sent

(future
  (println “5s to close the connection”)
  (Thread/sleep 5000)
  (while true (swap! a inc) (println “filling buffers if any!“)))

cgrand 2017-04-07T09:32:54.148591Z

and the thread keeps doing its stuff

pesterhazy 2017-04-07T09:40:04.247312Z

hm

pesterhazy 2017-04-07T09:40:25.252460Z

so nREPL must have some code in place to swap out a null output stream for *out* after disconnect

pesterhazy 2017-04-07T09:40:51.258189Z

I think that's a good (non-surprising) default behavior

cgrand 2017-04-07T09:41:11.262688Z

I think it just attepts to send the message back, gets an exception and keeps going

cgrand 2017-04-07T09:41:34.268220Z

that *out* is not directly tied to the socket outputstream

cgrand 2017-04-07T09:57:27.487905Z

A cursory review of nrepl shows me that this should not happen https://github.com/clojure/tools.nrepl/blob/master/src/main/clojure/clojure/tools/nrepl/transport.clj#L101

cgrand 2017-04-07T13:26:06.243331Z

So now elided kvs are rendered as maps (when fetched, previously a seq of pairs was returned)

cgrand 2017-04-07T13:27:14.264623Z

and :bye got some attention:

(spec/def :unrepl/bye-payload
  (spec/keys :opt-un [:unrepl.bye/reason :unrepl.bye/outs :unrepl/actions]))

(spec/def :unrepl.bye/reason #{:disconnection :upgrade})

;; describes what happen to background outputs after the `:bye` message: 
(spec/def :unrepl.bye/outs
  #{:muted ; they are muted (think `/dev/null`) 
    :blocked ; writing threads are blocked
    :closed ; they are closed (unless handled, the IO exception kills the writer)
    :cobbled}) ; everything is cobbled together (like with a plain repl) 

cgrand 2017-04-07T13:28:37.291140Z

and there’s a :reattach-outs action to recover outs in another repl

cgrand 2017-04-07T13:40:33.526158Z

but it’s kind of stupid of advertising :reattach-outs on :bye because depending on how you lost the connection you may not get it.

dominicm 2017-04-07T14:20:28.389020Z

I have a cli tool for nrepl that I wrote, that sometimes gets killed before the messages have been received. nREPL throws exceptions when it can't send the message back. It's really annoying. The exception gets written to the stdout of the "host" process.

thheller 2017-04-07T15:23:32.863759Z

not a fan of the overall format but very cool nonetheless

thheller 2017-04-07T15:23:59.873974Z

how do you make these .gif btw?

cgrand 2017-04-07T15:28:07.970391Z

the gif doesn’t display right for me

thheller 2017-04-07T15:30:07.018604Z

works fine for me

cgrand 2017-04-07T15:31:09.044138Z

gif recipe: https://gist.github.com/dergachev/4627207

thheller 2017-04-07T15:32:33.076341Z

cool thx for the notes

cgrand 2017-04-07T15:32:45.081038Z

@thheller re: format, me neither but it’s a dozen CSS lines

cgrand 2017-04-07T15:33:56.108161Z

I’m experimenting with the protocol, not the rendering

thheller 2017-04-07T15:34:36.124056Z

ah right, forgot its already html 😛

cgrand 2017-04-07T15:36:19.163783Z

I’m longing to have a selhosted cljs impl of unrepl, to connect “hyrepl” to its own processes

thheller 2017-04-07T15:44:35.351464Z

hmm? whats wrong with the CLJ repl?

cgrand 2017-04-07T15:45:56.382746Z

you mean the CLJ-CLJS repl or the CLJ one?

thheller 2017-04-07T15:46:19.391532Z

why does it have to be self-hosted cljs?

cgrand 2017-04-07T15:47:31.419348Z

because slef-hosted is simpler to deal with

richiardiandrea 2017-04-07T16:18:46.125334Z

@cgrand you can have a look at replumb for that, I haven't update it in a while (sorry!) but I am was using it for <http://clojurescript.io|clojurescript.io> as self-hosted repl

cgrand 2017-04-07T16:27:21.303295Z

Thanks!

richiardiandrea 2017-04-07T16:33:03.423603Z

it was an attempt to unify the code that powers planck (lumo was not out yet), the code for <http://clojurescript.io|clojurescript.io> is under Lambda-X/cljs-repl-web on github and the file that uses replumb is here -> https://github.com/Lambda-X/cljs-repl-web/blob/devel/src/cljs/cljs_repl_web/replumb_proxy.cljs