Move server + handler execution to top-level
Currently, servers are executed in a pod, which means that any server state is inaccessible from e.g. a top-level REPL. In discussions with boot-http users, it seems that it would be better to sacrifice the classpath isolation afforded by the pod for the improved accessibility of executing outside of one.
If the implementation is not too tricky, there could be an option for whether to use a pod or not, thus preserving the current behavior once the default changes.
I was just searching around to see if something like this was possible and saw this open issue. I just thought I'd weigh in that it would be really amazing to have REPL access to the server state. I just started using boot-http to prototype a small client-server app, and the ability to use http-kit with a custom ring handler means that it is fairly easy to add websocket communication using something like sente. Sending data back and forth using REPL commands would be great for troubleshooting and prototyping.
Yeah I've yet to take this on, but thinking about it, I'd like to maintain the default "in-pod" behavior and add the non-pod execution as an optional flag. In one of my apps, the isolation is actually useful as some namespaces depend on the environment to set certain vars, and serve creating its own pod allows for setting up multiple environments in one Boot pipeline.
I still think it's a good thing to add though, for the access to state that you mention. PR would be happily accepted along the lines above, if you want to take a shot. I'm not sure when I'll be able to get to it.
Thanks for the reply. I think you're right that the pod behavior is useful should be the default. I spent some time experimenting with this, and I think I get the desired functionality by starting an nREPL server inside the pod. An additional benefit of this is that I think you could start multiple serve processes, have REPL access to any of them when desired, and they would remain isolated.
My idea for how this functionality could be accessed in boot-http is that via command line you could use a -n flag for nREPL:
boot serve -n wait
which will start an nREPL and print out:
boot-http nREPL started on port [PORT] on host 127.0.0.1
You could then connect using:
boot repl -c -p [PORT]
If you want control over the host and port, you can configure it from within your boot.build file:
(task-options!
serve {:handler 'server.core/handler
:nrepl {:port 3001 :bind "127.0.0.1})
Anything truthy will start the nREPL, but if it can find :port and :bind, it will use those parameters when starting the nREPL server. I thought this might be a reasonable API because the command line invocation is simple, but you still have the power to set the nREPL port and address if you want.
Do you think this sounds like a good addition? If so, I can try to get you a pull request.
Chris that sounds beyond awesome! I agree 100% with the API.
One remaining question is whether the top-level option would still be useful in other cases... I suspect it would be a nice option to have, for when you want an actual (e.g. boot.user>) REPL but also want access to server app state, without having to run two different nREPL servers... But I can tackle that another time.
Thanks for pushing this forward.
Great! I will give this a shot. Your point about the top-level option is a good one as well. I think there are other use cases that would also benefit from this option. I'd suggest that the top-level option is accessible using the -t flag, or {:top true} from the boot REPL. If I have time and can figure all of this out, I will try to add both. Otherwise, I'll focus on the within-pod nREPL.
If I run into any problems while working on this, I will ping you here. Thanks!
Fantastic! Thanks! :+1:
To the devs: from an outside perspective this issue (still open and discussing the in-pod repl) looks like support isn't here yet; perhaps there are still aspects that are unsupported?
To prospective users: the discussion above looks like it was fruitful; you can launch a server with an in-pod repl:
(deftask dev-with-repl []
(comp
(serve :reload true
:port 3000
:handler 'your-service.routes/service-main-handler
:nrepl {:port 9990 :bind "127.0.0.1"})
(watch)))
Yeah @atstp , you are right. You can launch an in-pod REPL, however my brief usage of that feature revealed one issue: nREPL middleware (defined in profile.boot for instance) isn't picked up, so in connecting to that REPL, Cider for example will complain.
I have yet to tackle this but I do think it would make for a nice option to be able to serve in a pod or at the top level, so to speak. That's why I've kept this open.
Hmm, I haven't run across any trouble so far, but it's likely there's an issue I haven't encountered.
For what it's worth, I'm using vim fireplace which depends on cider-nrepl, so I followed boot's suggesion about modifying ~/.boot/profile.boot.