boy am I glad I found this #
Awesome repo! Thank you for doing this!
Yeah we’re discussing it. It’s in my queue right now.
========== (summarizing a discussion with n@ickbauman) So as it turns out, it's possible to call "eval" in clojure code running on GAE. For example, you can take the standard lein new cljgae-template, change the :h3 to
[:pre (eval (read-string "(+ 40 2)"))]
-- and it would work.
This opens up the following really cool possibility: instead of doing a "lein ring uberwar + deploy" every time, it should be, in theory, sposible to:
(1) up load some *.clj files to datastore / cloud storage
(2) have the dev-appspot server, on every request, pull the *.clj files from datastore/storage, and eval it on the fly for the http handler
This reduces the number of "lein ring uberwar + deploys" down to only (1) you have to add new server side dependencies and (2) when you are uploading the final AOT classes.
There's some non-trivial engineering effort (atleast from my perspective) involved to get this to work. If you're good with getting eval to work with entire files (instead of simple "(+ 40 2)" expressions) or can contribute in other ways, please let @nickbauman [ author of cljgae-template] know
Getting this to work may drastically increase all of our productivity via reducing deploy times.☝️ This is a big deal.
what problem is this addressing? repl-like development?
Howdy folks. FYI: https://clojurians.slack.com/archives/boot/p1484852190009405
@nickbauman, @qqq: not sure what you’re planning to do with eval, but if you’re looking for REPL-like development please check out boot-gae before you put in too much work. It reloads changed clojure source on page refresh.
It differs from most approaches to Clojure on GAE in that it does not AOT compile the entire app, only the servlet and filter stubbs, and it generates all the XML config files from edn files. Also supports both servlet-based and service-based apps from the same codebase.
There’s quite a bit of documentation explaining the implementation techniques, so you might be able to use something similar for your leiningen code.
see also https://github.com/migae/datastore/blob/master/README.adoc. this is completely separate from boot-gae. haven't worked on it for many months, but looking over the docs, it seems to make sense. ;)
Yeah I haven’t been able to spend much time looking at that, @mobileink but it seems promising.
It’s a big problem with developing with clojure on appengine.
@nickbauman buleeeve me! i've been hacking at this for several years - tried leinengen, tried maven, tried gradle. with boot i believe i may be almost done with thw blasted thing!
i still have a warm corner of my heart reserved for leinengen, but boot is in an entirely different league.
🙇 I think it’s time for me to get more familiar with you work.
that would be nice - its lonely out here!
:highfive:
What’s going on with the flexible environment?
fwiw i'm totally in favor of a leinengen solution. just not sur how it works, since i haven't worked with it for quite a while. boot is very different
re: flexible env: no free tier, that's all. but it cant be that much different.
i'm just happy that i got service-based apps to work. i think; let's wait and see what happens when sb usescit in anger.
anyway, @nickbauman , don't want to rain on your parade, but i also hate to see people spending effort reinventing the wheel. not that my whell is the best wheel, but it's sufficiently unusual that i think it's worth your while to take look.
Yeah I’ve never looked at boot very closely.
If the parade needs raining on, please go ahead and rain.
The point is it will move all of us forward.
😉
i'll note also that i'm only talking about build/test/deploy stuff, not apis for GAE services like datasore. in principle that atuff should work with any build systwm.
i like your attitude! par for course with Clojure, i guess. :)
caveat: boot does have a learning curve. but the devs on the boot channel are unbelievable tesponsive and helpful.
re: flexible env: if anybody wants to pay me large sums of money to make it go i'm game!
lol
could happen
@mobilelink: [ all in context of boot-gae ] 1) what is servlet-based vs service-based approach 2) this entire time, I was under the impression that to update a gae app, we have ot deploy, and during deploy, we SEND AN ENTIRE NEW WAR -- from what you're saying it sounds like it's possible to UPDATE ONLY A PORTION OF THE APP INSTEAD OF SENDING A NEW WAR -- is this true? 3) does boot-gae requires flexible env, or does it also work on the standard env?
@mobileink : ^^^
Q3 answered from front page of docs: Note Currently only the Standard Environment is supported. The Flexible Environment is not supported. Okay, 2 questions left: @mobileink
@qqq q 1: see the doc, there are links to the ggogle docs. briefly, a "servlet app" is a standalone app. it can have multiple servlets, but calling from one servlet to another is complicated. a "service-based" app is an assembly of one or more servlet apps. they communicate by http requests. it's kinda hard to explian; best bet is to read the google docs.
@mobileink : q1, fair enough, will read the docs; q2 -- how are you doing these updates so effeiciency, are you only uploading 'part of the full proejct' very time?
@qqq: q2: you do not need to build, pkg, updste, restart, etc. every time you change your clojure source.
fighweel can recompile locally, but how do you update remote gae without build/pkg/upload/restart ?
read the doc for gen-class very carefully. the servelet container searches for a class file, loads it, and sends it a "service" message. the class file created by gen-class forwards that to the appropriately named clj fn, in the appropriate clj namespace. so we only need to aot-compile the stub that does the forwarding. boot-gae creates that class "invisibly".
@qqq what does " update remote gae" mean? boot-gae allows you to live update locally, using the dev server. deployment to prod is a whole 'nither matter.
updating locally via dev server I can do already via lein + figwheel
it's the "deploying to remote gae server" part that takes long right now 10-20 seconds
I'm tring to understand how migae cuts down the "deploy to remote gae server" time
you only need to restart the dev server if you need to add/remove servlets or filters
what is a "remote gae ssrver"? you mean the prod, in-the-cloud server?0
yes
"remote gae server" == I mean the gae server in the cloud
boot-gae makes it easy to develop gae stuff locally, with a quasi-REPL, that's all.
updating locally is not a problem, I just tell cider to replaod buffer, and BAM, I'm running new code
I can develop stuff locally without migae though too
the problem we're trying to solve is "how do we cut down on deploy time"
right now, deplying to remote cloud gae takes 10-20 seconds, we want to reduce that down to (1) upload a new *.clj file, and (2) have remote cloud gae take that clj and run it on the fly
how do yu so that? jeez, maybe i'vw been wasting my time. ;)
no no, I think the work you're doing is very interesting and I'm glad we're having this conversaion; I'm being exposed to lots of into I'm not used to; give me a few secs to describe my current work env
for deplying to cloud/gae:
I type "sh deploy.sh", which then does:
lein ring uberwar
some other complicated stuff to put resources/xml files in right place
runs app_cfg.sh update
then I wait 10-20 seconds
to develop locally:
1) I fire up "lein repl" (actually just cider-jack-in)
2) I run four lines in repl, which then (a) starts up jetty/ring using the #' trick to update handlers and (b) starts up figwheel
3) I edit some file, and I save. For cljs side, figwheel auto recompiles and updates the browser.
4) If I'm editing server side code, I run cider-reload-buffer, which reloads the current buffer, and the #' trick causes the running jetty server to pick up the new handler
^^ taht's my entire dev setupi'm very interested and terrified. if i find out i've spent many months figuring out the hard way to do sth everybody else already knew how to do... well, what else is new?
jetty server: are you running sth orher thsn the gae devserver? i started down this path years ago with appengine-magic, which did sth like that. boot-gae only ever uses the devserver
what is the #' trick?
@mobileink: 1) what you have done [and also what @nickbauman has done] is far bigger than what I did: both of you actually wrapped google service libraries all I have at the moment is that I got http://lambda-startup.com/developing-clojure-on-app-engine/ to work -- and I'm still reading gae/java docs
@mobileink : the #' trick see the comment by Tim in the above link:
Hi Oliver,
Great post, thanks for all the details.
Regarding reloading routes, the trick is to pass the var pointing to your handler to jetty.
(def handler (environment-decorator handler/app))
(run-jetty #’handler {:port myport :join? false})
basically, #' causes it to "use most recent binding of var", which means when you reload the buffer, the ring/jetty server will run the latest handlerit has to do with (1) #' using the var rather than the binding and (2) vars get auto dereferenced if they're in the place of a function call