Fork me on GitHub
#yada
<
2016-07-26
>
mccraigmccraig08:07:34

@severed-infinity: websocket handling is pretty easy with aleph - i have a vanilla ring handler which handles websockets, right alongside my yada resources - http://aleph.io/examples/literate.html#aleph.examples.websocket

lmergen12:07:12

i might as well ask this question here, but how does juxt's modular relate to danielsz's system ? they appear to be solving the same problem, is it not ?

dominicm12:07:13

I think modular predates system. But I'm not sure.

dominicm12:07:30

system has changed a lot since I last used it though

lmergen13:07:56

ok, thanks

lmergen13:07:01

i'm very confused about what the best way to deploy yada services is... it seems like the boot community really likes to run production systems from within the boot environment, rather than using an uberjar ?

martinklepsch13:07:32

@lmergen: you can totally run stuff from an uberjar

lmergen13:07:13

yeah, it just appears as if it's a bit more complicated to get working than under lein... or rather, i'm trying to solve errors with the generated .jar for about 3 hours now, without any luck

martinklepsch13:07:27

what you prefer depends on a bunch of factors that might vary from team to team

martinklepsch13:07:32

@lmergen: let's sort it out in #C053K90BR

martinklepsch13:07:33

@dominicm: FWIW, I recently started using danielsz/system (only for the reloading + boot features) and it's amazing, like crazy amazing. If it's been a while since you tried it you might want to give it a try again šŸ™‚

dominicm13:07:10

@martinklepsch: I used the components from it way back. I opened a couple issues iirc.

dominicm13:07:41

Just to show how different system was when I used it šŸ˜›

martinklepsch13:07:50

right the components I don't use at all (they still exist)

lmergen13:07:55

yes, it seems like the past year, many of these systems have matured a lot

malcolmsparks13:07:06

I'm well aware of 'system' but haven't taken a proper look recently. Out of interest, what does system have that edge doesn't?

lmergen13:07:23

system is like modular

malcolmsparks13:07:08

Yes, but besides prebaked components.

malcolmsparks14:07:20

@lmergen: one of the reasons I dislike the current fashion for building/deploying uberjars is the differences that begin to pile up between dev and prod. If it takes you 3 hours to figure out how to run something you were able to run fine in dev then that's what I'm talking about. And if it breaks in prod, who besides the individual that built the pipeline can fix it? I believe we have blindly inherited practices from C/C++ and forgotten the ancient ways of Lisp.

lmergen14:07:03

yes, i have been bitten by that in the past, especially when it comes to things like configuration, logging, etc

malcolmsparks14:07:09

@lmergen: od course, this is a general point I'm making, completely unhelpful !

lmergen14:07:06

so, if i understand it correctly, you are saying that we should just create a prod task in build.boot, and run it from there ?

malcolmsparks14:07:20

Yes, boot run -p <profile>

malcolmsparks14:07:05

We even have integration wuth systemd, via a systemd script parameterized with the profile.

martinklepsch14:07:49

@malcolmsparks: system gives you a fileset-based reloading workflow, restarting your system when (selected) files change

malcolmsparks14:07:01

Yes, you understand it right. However, this is still a 'maverick' choice, the vast majority of Clojure devs do traditional build and CI/CD

lmergen14:07:22

that is actually fairly reasonable

malcolmsparks14:07:00

There's a systemd script in the root dir of edge now

malcolmsparks14:07:58

We've rum some client projects like this in prod, plus internal stuff. I can't say we've seen any increase in outages as a result.

lmergen14:07:07

oh geez, i didn't even see that

malcolmsparks14:07:49

The main advantage is support. If there's ever a support issue I can ask a dev to investigate and they're like "fine, I understand this, it's almost exactly like things are on my dev machine"

lmergen14:07:49

yes, i really like the idea of this, however, i think the plan falls apart when you're trying to deploy into more elaborate systems (e.g. AWS Elastic Beanstalk)

malcolmsparks14:07:31

Yes it does (fall apart). We have some systems on AWS BS via docker and uberjar. I find them a pain to setup and debug but that's a personal opinion. I think the autoscaling feature is mostly oversold, only some systems actually need it. I prefer to build in headroom than scale out, because I don't accept scaling out is ever inexpensive

lmergen14:07:35

well, that's an entirely different discussion i think

lmergen14:07:26

(i also believe the autoscaling feature is oversold, or rather, it's not being sold for the right reasons)

malcolmsparks14:07:37

My belief is IT is heavily biased towards ops today, they wield the most influence in large orgs today.

lmergen14:07:02

i agree, as someone running a video serving startup, operation (automation) is a fairly big part of our development

nha14:07:04

been hit by the uberjar/different prod thing quite recently (exacerbated by aot in my case, which somehow made me loose the environnement config). Have been looking at edge, interesting (I still build an uberjar at this point) I like the idea of a task taking a profile as parameter. And the conf file approach so I will probably use aero and steal you approach šŸ™‚ One problem I had was to coerce the values from strings to ints/booleans etc. using clojure.spec though (I had to namespace some keys and reading them in a task made them namespaced under user.boot and when aoting made them namespaced under clojure.core..).

lmergen14:07:57

@malcolmsparks: i also think that the influence of ops has become bigger due to the continuous deploy trend

lmergen14:07:24

but perhaps you're correct that this is being translated the wrong way -- instead of hardening our production environment using all kinds of awesome bells and whistles, perhaps the best way is to make the production environment more like dev

keithmantell14:07:51

Iā€™d just like to say that this has been a very interesting thread - lots for me to process. Thx

nha14:07:31

Ah - turns out I can't use aero in my case since it uses clojure.core.edn to read the file (which is fine), but it does not support auto-namespaced keys.

nha15:07:31

So I use aero like this now - not sure I'm completely happy with my code but I'll try and see :

(defn ns-tlk
  "keywordize keys. namespaced keys boot.user and clojure.core will have backend.conf as namespace"
  [m]
  (let [f (fn [[k v]]
            (if  (and (keyword? k)
                      (or (= "boot.user" (namespace k))
                          (= "clojure.core" (namespace k))))
              [(keyword (str 'backend.conf) (name k)) v]
              [(keyword k) v]))]
    (walk/postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m)))


;; replace read-config from aero to load-file and allow the use of namespaced keywords

(defn read-config
  "Optional second argument is a map that can include the following keys:
  :profile - indicates the profile to use for #profile extension
  :user - manually set the user for the #user extension
  :resolver - a function or map used to resolve includes."
  ([source given-opts]
   (let [opts (merge aero/default-opts given-opts {:source source})
         tag-fn (partial aero/reader opts)
         ;; read the file in here. That makes it easier to coerce (and dev)
         ;; since the namespace is the same
         ;;  pass a string already with correct namespaces
         config (edn/read-string {:eof nil :default tag-fn} (str (ns-tlk (load-file source))))]
     (#'aero/get-in-ref config)))
  ([source] (read-config source {})))

(defn get-conf
  "returns the file configuration"
  [conf]
  ;; TODO memoize ? defonce a {} ? have an env var/record here ?
  (let [edn (read-config (case conf
                           :dev "resources/dev-conf.edn"
                           :prod "resources/prod-conf.edn"
                           (throw (Exception. (str "Not a config " conf)))))
        c (s/conform ::config edn)]
    (if (= :clojure.spec/invalid c)
      (do
        (s/explain ::config edn)
        (throw (ex-info "Invalid spec " (s/explain-data ::config edn))))
      (util/drop-ns-keys c))))
EDIT: no need to use all that, clojure.spec supports un-namespaced keys šŸ™‚

dominicm15:07:37

A yada question, how do I do authorization that a user must be logged in?

dominicm15:07:36

I'm also not sure roles align with my preferred usage. I think a better idea is to fetch it from the database for every request, this makes banning a user or changing their roles much easier. I'd be interested to know I'd go about setting this up.

mccraigmccraig17:07:38

@dominicm: i use a yada interceptor / ring handler which checks for a JWT token header, which i generate with buddy.sign