Reload app running in lein repl

815 views
Skip to first unread message

Michael Bevilacqua-Linn

unread,
Mar 19, 2013, 8:42:01 PM3/19/13
to pedesta...@googlegroups.com
Howdy,

Is there any way to reload an app running in the lein provided REPL after making changes like, say, adding a route?  

The only thing that worked for me was to kill the REPL and restart it...

Thanks,
MBL

Gabriel Horner

unread,
Mar 20, 2013, 12:03:36 PM3/20/13
to Michael Bevilacqua-Linn, pedesta...@googlegroups.com
On Tue, Mar 19, 2013 at 8:42 PM, Michael Bevilacqua-Linn <michael.bev...@gmail.com> wrote:
Howdy,

Is there any way to reload an app running in the lein provided REPL after making changes like, say, adding a route?  

Yep!  It would look as follows where my-app should be your app's namespace:

$ lein repl
my-app.server=> (dev)
nil
dev=> (start)
nil
;; app is now viewable

;; make route changes
;; then reload changed file
dev=> (require 'my-app.service :reload)
nil
dev=> (restart)
nil

;; see your changes
 

The only thing that worked for me was to kill the REPL and restart it...

Thanks,
MBL

--
You received this message because you are subscribed to the Google Groups "pedestal-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pedestal-user...@googlegroups.com.
Visit this group at http://groups.google.com/group/pedestal-users?hl=en.
 
 

Tim Ewald

unread,
Mar 20, 2013, 12:30:37 PM3/20/13
to Michael Bevilacqua-Linn, pedesta...@googlegroups.com
Michael,

It depends how you work. If you work in an editor with an integrated
repl, you can simply edit and recompile your routes without restarting
your web server or repl.

When the interceptor that handles routing gets created, it is given
either a route table or a function that can be called to get a route
table. In dev mode, we give the router a fn that returns the latest
compiled route table. So if you change the route definition and
recompile the route table, the changes will be used for next request.
You don't have to restart the web server or the repl.

The lein pedestal-service template sets up dev mode for you, check out
the generated dev/dev.clj file, which includes this:

(def service (-> service/service
(merge {:env :dev
::bootstrap/join? false
::bootstrap/routes #(deref #'service/routes)})
(bootstrap/default-interceptors)
(bootstrap/dev-interceptors)))

This code takes the map that configures your production service and
modifies it for dev use. Note that it sets the value of the
:bootstrap/routes key with an anonymous fn that returns the latest
compiled routes.

But all of this assumes you are in an environment that makes it easy
to edit and recompile, like emacs. If you run a standalone editor and
a command line repl in a separate process, this approach doesn't work.

We have a proof-of-concept for a router that reloads routes from a
saved file, without explicitly recompiling. It also reloads the
namespaces you depend on, but not the ones they depend on. That could
certainly be done, but we stopped short because it wasn't clear we
need this functionality and because constantly reloading all your
namespaces requires some discipline in structuring your code.
Internally, we mostly use emacs.

Which mode to you work in?

Tim-

On Tue, Mar 19, 2013 at 8:42 PM, Michael Bevilacqua-Linn
<michael.bev...@gmail.com> wrote:

Michael Bevilacqua-Linn

unread,
Mar 20, 2013, 8:05:45 PM3/20/13
to pedesta...@googlegroups.com, Michael Bevilacqua-Linn
Hey Tim,

Gabriel's suggestion works great in the lein REPL for my simple "hello, world" where I just added a new route and handler function in the same file.  Of course it seems painfully obvious that it should, in retrospect :-)

I generally work in either Vim + Vimclojure (though that project is now mostly dead) or Eclipse + Counterclockwise, both of which have their own embedded REPLs.  I was just playing around with LightTable and following the Pedestal hello world example which uses the Lein REPL.  Trying to figure out just what the heck a instarepl in LightTable is plus the fact that the hello world intro uses leinrepl is mostly what prompted this question.

As for the proof-of-concept router you mentioned, yeah I'm not sure that I'd find that useful even when using a separate REPL like the one lein provides...  Shouldn't I always be able to just reload the relevant namespaces (assuming no AOT or changes to protocols, etc), to get my changes into the REPL?  And if I'm working in a more integrated environment running in dev mode, I should just be able to evaluate whatever namespace I've got my defroutes in, along with any handler functions the routes refer to, no?

Thanks,
MBL

John Chijioke

unread,
Jun 17, 2013, 2:52:29 AM6/17/13
to pedesta...@googlegroups.com
Please make it easy to reload whatever namespaces I'm depending on or give me the option to do so. This issue is impeding my development efforts. I modify a development namespace and I can't get the 
interceptor process to reread the updated version of my interceptor namespaces and their dependencies. What is going on?

Tim Ewald

unread,
Jun 17, 2013, 8:44:30 AM6/17/13
to John Chijioke, pedesta...@googlegroups.com
John.

If you are working in a repl-attached editor, you can simply recompile the modified code. If you aren't in a repl-attached editor or you don't want to have to recompile explicitly, you can run the dev/watch function to start a thread that will monitor code for changes and reload as needed. This support was added recently based on a sample we've had around for a while. If you don't have a watch fn in your dev namespace (because you generated your service before support was in), follow the instructions in this post [1] to update your service.



--
You received this message because you are subscribed to the Google Groups "pedestal-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pedestal-user...@googlegroups.com.

John Chijioke

unread,
Jun 17, 2013, 11:19:29 AM6/17/13
to pedesta...@googlegroups.com
Hi Tim, 
It seems I mistakenly sent you a direct message. I'm meant to post it here. 
Thanks for the prompt reply. It's somehow strange. I've been working in emacs for quite some time now and I'm used to such workflow as you've just described. I'm surprised that the app-development-server var in the dev.clj revision I'm using is not picking up my changes even after (require 'my.namespace :reload). Is this caused by the absence of ns-tracker in my project.clj? 

John

On Wednesday, March 20, 2013 1:42:01 AM UTC+1, Michael Bevilacqua-Linn wrote:

Tim Ewald

unread,
Jun 17, 2013, 12:54:02 PM6/17/13
to pedesta...@googlegroups.com
John,

The default behavior for the server running in dev mode is to pick up the latest compiled routes and everything they refer to on each request. I normally build out a service by adding routes and loading with C-c C-k in nrepl then hitting the new route from curl or a browser. That won't pick up other changes to the service definition - like if you change options in your service map. For that you have to reload those namespaces and maybe also restart the http server, depending on the change. The auto-reloading instructions I sent should reload the code as it changes, but it does not auto-restart the web server, as that would get time consuming. So it may depend on the precise change you are making, but in most cases one or the other of these techniques should work.

Tim-


On Mon, Jun 17, 2013 at 11:10 AM, John Chijioke <johnb...@gmail.com> wrote:
Tim,

Thanks for the prompt reply. It's somehow strange. I've been working in emacs for quite some time now and I'm used to such workflow as you've just described. I'm surprised that the app-development-server var in the dev.clj revison I'm using is not picking up my changes even after (require 'my.namespace :reload) and (stop) (start). Is this caused by the absence of ns-tracker in my project.clj? 

John
Reply all
Reply to author
Forward
0 new messages