Fork me on GitHub
#clojure
<
2016-02-03
>
cfleming00:02:55

@jkrueger: So how are you building your Clojure? Are you just shipping as source?

spradnyesh00:02:01

for a service that has a lot of video uploads, how do i chose between clojure and clojurescript + nodejs?

jethroksy03:02:22

@spradnyesh I think the argument for node comes when you have short lived connections, because node spins up faster than the JVM, but if your service is long running then I personally feel that the JVM is a better option because of its rock solid foundation.

jethroksy03:02:16

Also I always had the feeling that profiling in clojure was a lot more mature, and this would be very useful if your service becomes slow and you want to figure out your bottleneck

jethroksy03:02:52

The plus side of CLJS is I guess, js everywhere?

mikera03:02:42

If you use cljc, it is relatively easy to have the same code running on both the server side and the browser. I'd definitely go with Clojure for the server side on average, better performance especially in highly concurrent situations. Startup time is pretty irrelevant for server applications.

jonahbenton03:02:52

hey @spradnyesh: how much is a lot of video uploads? you are streaming to your own storage or to someone elses?

shayanjm04:02:05

Question: has anyone here used kafka & clojure together?

shayanjm04:02:22

bonus points if you’ve used this library and would let me pick your brain a little bit simple_smile https://github.com/gerritjvv/kafka-fast

jimmy04:02:24

hi guys I have a question regarding core.async, I want to untap and close a channel when I unmount a component. My strategy is to send a message so it can closes itself, but I'm not so familiar with how to do it right with alt! and go. This is the code :

(async/tap components-mult c-tap)
     (go
       (alt! c-tap ([v]
                    (if (= (:action v) :close-tap)
                      (do
                        (async/untap mult c-tap)
                        (close! c-tap))
                      (do
                        (prn "v" v)
                        (do-stuffs v)
                        (recur))))))))

bfabry05:02:19

@shayanjm: used kafka, not that library

shayanjm05:02:33

bfabry: gotcha. having trouble spinning up consumers using that library

shayanjm05:02:53

which is unfortunate, because making producers work was (deceivingly) simple

cddr06:02:40

Is there any way to set things up so that Class.forname finds a var defined by a reify?

bfabry06:02:36

@cddr depends when the thing is reified. I just used Class.forName to find one that was created during compilation. but if it's at runtime I doubt it

cddr06:02:55

Oh, that might be good enough. I was just testing at the repl and it couldn't find it

bfabry06:02:33

user=> (compile 'bar.foo) bar.foo user=> (use 'bar.foo) nil user=> (str (class reified-thing)) "class bar.foo$reify__2350" user=> (Class/forName "bar.foo$reify__2350") bar.foo$reify__2350 user=>

bfabry06:02:49

so you'll need to aot the reify statement probably

bfabry06:02:17

11326-storage:bar bfabry$ cat src/bar/foo.clj (ns bar.foo) (def reified-thing (reify Object))

cddr07:02:57

Sweet! I think that's going to work. Thanks @bfabry

acron09:02:46

@shayanjm: funnily enough I'm integrating kafka as we speak, using that libary

acron09:02:21

@shayanjm: I also had trouble with consumers because the library mandates a redis-based setup and I am too unfamiliar with kafka to stray from the ZK setup, so I've actually ended up using clj-kafka for the consumer and kafka-clj (kafka-fast) for the producer

jasonbell10:02:45

@shayanjm: worth having a look at Bifrost which uses Kafka to write to S3. https://github.com/uswitch/bifrost

mpenet10:02:34

there's also https://github.com/pyr/kinsky worth mentioning, it's relatively recent but knowing the author it should be a quality lib.

pyr10:02:03

thanks for the kind words simple_smile

pyr10:02:58

kinsky targets kafka 0.9.0, and so far if you do, safe for the java client there is no other clojure lib

dm310:02:13

@pyr, quick question - did you try ztellman/manifold and if so, why did you choose core.async for kinsky?

pyr10:02:16

I'm not a 100% sold on manifold just yet.

dm310:02:08

is it mostly reliability concerns or API-wise?

mpenet10:02:37

you can use them together if that's your thing (manifold can interface with core.async), or write a thin interface to it like kinsky.async does for core.async

pyr10:02:14

@dm3: but it really boils down to our use of core.async internally

pyr10:02:32

and kinsky is a factor-out of our kafka lib

dm310:02:45

sure, just wanted to hear an opinion simple_smile

pyr10:02:58

when stuff ends up copied across several projects, we often end up publishing a lib

pyr10:02:26

i didn't split the core.async part like i did in mesomatic

pyr10:02:31

but might do that eventually

pyr10:02:54

the idea behind kinsky is to factor our more

pyr10:02:51

especially our processing logic which relies on dual topics + log compaction

dm311:02:01

event sourcing with snapshots in kafka simple_smile

pyr11:02:09

@dm3: and in general, I would say I am very conservative with external libraries, I tend to default to clojure.core and then bolt-on as few as possible

dm311:02:11

I can see your point. Although I default to manifold instead of core.async if I don't need cljs

dm311:02:31

however not running anything super critical

pyr11:02:18

@jasonbell: @shayanjm: unrelated to clojure, but kafka connect will now service that use case well also

martinklepsch11:02:22

anyone some favorite clojure util libs that have stuff like map-vals? ideally cljc

martinklepsch12:02:01

@dm3: perfect, thanks!

nberger15:02:55

@lvh: I think you can try with conso (https://clojuredocs.org/clojure.core.logic/conso) and some recursion to define the goal (`l/membero result events`) for every member of results. You could also try with permuteo and appendo but not sure if it will work (they have to be proper collections, so they have to be grounded). You can also try asking in #C0566T2QY simple_smile

lvh15:02:58

nberger: thanks for the hints! my attempts at writing a recursive version always fell short in that it expected to know a priori how big the result set should be

lvh15:02:01

I may be able to statically define that by inspecting the query I’m getting in (that’s a data structure)

sashton15:02:14

I've got a mental block, there's got to be a way to simplify this: (if-let [v (:v m)] (hash-set v) (hash-set)) I'm trying to end up with either an empty set out a set of one item, and not a set containing nil. A separate issue I have is that i can't find a curly brace key on my phone :p

shayanjm15:02:49

@acron: ahhh, yeah I think the guy brings up some good points about ZK, so I wanted to try out his redis set up

shayanjm15:02:55

it looked cool, too bad I can’t make it run 😕

jethroksy16:02:04

@sashton: (conj (hash-set) (:v m))?

jethroksy16:02:12

(that's assuming you can't find your curly brace key

jethroksy16:02:09

if you do probably (conj #{} (:v m))

sashton16:02:21

@jethroksy that leaves me with a set containing nil, rather than an empty set

jethroksy16:02:50

@sashton: my bad i meant into

jethroksy16:02:02

wait i had this working just now

jethroksy16:02:41

wait into should work

jethroksy16:02:08

(into #{} (:v m))

sashton16:02:13

@jethroksy I should have mentioned that the value in :v is not a collection: (into (hash-set) (:v (hash-map :v 1)))

sashton16:02:38

That would throw an error

jethroksy16:02:14

you could use quote/unquote

jethroksy16:02:24

but i'm not sure if that's simpler anymore

jethroksy16:02:52

ah wait the nil problem would persist

jaen16:02:40

Quote/unquote is probably a bad habit because i don't think this won't work in Clojurescript.

jaen16:02:44

@sashton: how about (if (some? x) #{x}) #{}) if I undertand you properly?

jaen16:02:15

hm, no that;s not exactly what you want

jethroksy16:02:09

feels like that's about as simple as it gets

jethroksy16:02:15

conj and into both won't work

jaen16:02:16

Yeah, I think (if-let [v (:v m)] #{v} #{}) is the most sensible option.

jethroksy17:02:34

is there a reason you need the empty set?

jethroksy17:02:37

today I learnt...

jaen17:02:45

Or alternatively something like this (or (some->> (:v m) (conj #{})) #{}) though it's a bit too clever maybe.

jaen17:02:02

One reason he might want a set I can think of is that he might be testing against the set.

jethroksy17:02:03

seq doesn't work on sets

jaen17:02:15

It doesn't?

jaen17:02:20

It should.

jaen17:02:33

Vectors aren't seqs either

jaen17:02:45

seq returns a sequence from the collection.

jethroksy17:02:47

i meant seq?

sashton17:02:11

Yeah I'm testing the set against another sequence

jaen17:02:01

so (seq #{1 2 3}) will net you a sequence of 1, 2 and 3 in some order.

sashton17:02:55

I guess at this point I should just wrap my if-let into a function and call it good.

jethroksy17:02:28

if having a nil inside doesn't hurt you could just #{:v m}

jethroksy17:02:54

i meant #{(:v m)}

sashton17:02:47

Truth be told, I am doing this in clojurescript, but it seems like it's general enough clojure functions so I asked here

sashton17:02:43

I could see a case where I need to check if the set is empty, so the nil gets in the way

jaen17:02:26

@sashton: incidentally

jaen17:02:32

do you have more of those maps?

jaen17:02:34

or just one?

jaen17:02:26

Because if you have more of those something like this might make sense (into #{} (keep :v ms))

sashton17:02:29

No, it's actually a nested map so I am calling get-in.

jaen17:02:15

Yeah, so what you're doing already is probably the most sensible then; (into #{} (keep :v [m])) feels to me like an attempt to be too clever.

vanrysss17:02:44

Is there a way to handle runtime config in an idiomatic way?

yenda17:02:48

is there a way to destructure a let binding with a prefix ?

yenda17:02:21

like r1/path r2/path...

jaen18:02:04

You mean :namespaced/keywords by that or something else?

ikitommi18:02:08

@polygloton, @seriousbug @jaen - of ring-swagger - not all Prismatic Schema records can be mapped to JSON Schema and vice versa. We are planning to build a pure Schema-based web/api documentation lib - should be a better fit for e2e Clojure(Script).

ikitommi18:02:50

Also, did a spike on visualizing schemas with Graphviz, UMLGraph-like. Might be useful as a repl-tool.

yenda18:02:57

jaen: I mean with the current form path method and params are redefined on the second line

yenda18:02:15

I would add something like r1 in front of them to avoid that

jaen18:02:12

Oh, I see. Nothing I'm aware of, you probably have to {path2 :path method2 :method params2 :params} unfortunately

jaredly19:02:09

@yenda: actually you can do (let [{:keys [:r1/path :r2/method]} req] (do-thing path method)) @jaen ; the namespace is stripped and the second half is used as the vbl name

jaen19:02:26

@jaredly: Yeah, I know about the namespace being stripped, but this is exactly the problem - in his case that would mean they would clash, wouldn't it?

Alex Miller (Clojure team)19:02:22

there's no trick to avoid that problem afaik

Alex Miller (Clojure team)19:02:59

other than renaming per the second set of keys like @jaen did above

jaredly19:02:21

ohhh right

Alex Miller (Clojure team)19:02:09

you didn't share what's in the let, but it's entirely possible there is some way to restructure the code at a higher level (via merge / merge-with)

uwo19:02:16

can anyone point me to some reference reading for making a (stuartsierra) component depend upon a core async channel? My case is very simple right now, I don’t need to broadcast to many components with a mult or anything like that.

jonahbenton19:02:15

hey @uwo- do you have a specific problem in mind? I haven't seen it documented explicitly but a common pattern is to keep 2 chans in component state- a work-chan and a stop-chan- and have component/start spin up a go loop that consumes work on work-chan and listens for a signal on stop-chan to stop work. component/stop would use stop-chan to signal the go loop to stop. Does that help? Of course there are many permutations depending on the needed communication pattern.

uwo20:02:42

@jonahbenton: hey, thanks. I should probably make use of that pattern. I’ve got a watcher component and a worker component, and I figured it would make sense to have them both depend on a channel; the watcher would produce and the worker consume. That said, I’m mostly curious where or when I add the channel to the system-map. Would the system construction look like this?:

uwo20:02:47

(defn system
  [cfg]
  (let [system-map (c/system-map :work-chan (a/chan 10)
                                 :stop-chan (a/chan)
                                 :watcher (ew.watcher/component cfg))]
    (c/system-using 
      system-map
      {:watcher [:work-chan]})))

jonahbenton20:02:12

@uwo gotcha- so the members of the system-map have to be components and participate in the lifecycle protocol, and chans can't do that directly. so maybe instead have 2 components, :watcher and :worker, have watcher create the channels and have them be part of component state, then have :worker depend on :watcher, and pull out the channels from :watcher state?

uwo20:02:28

oh? Did I misunderstand this quote from the library? Any type of object, not just maps and records, can be a component if it has no lifecycle and no dependencies. For example, you could put a bare Atom or core.async Channel in the system map where other components can depend on it.

Lambda/Sierra20:02:40

channels can be in the system map.

jonahbenton20:02:32

ah, indeed, sorry, i misspoke, was speaking from personal preference has been to keep resources within components so that lifecycle of those resources are managed together

jjttjj23:02:12

is referring directly to reloaded.repl/system in an application bad? like this example: https://github.com/danielsz/sente-system/blob/master/src/clj/example/my_app.clj#L63

jjttjj23:02:19

trying to figure out how to accomplish that same thing, accessing a sente component's members, but it seems like the way it's done there isn't ideal?

jaen23:02:04

Use something that doesn't require you to define things globally, I suppose?

nkraft23:02:06

@bfabry: Cascalog looks great but I can't wrap my mind around it. I don't come from a datalog background. Just trying to do something simple like a substring search in a field seems pretty obtuse. Maybe it's just me. Guess I'll have another look at PigPen.

jjttjj23:02:35

jaen: thanks, so you're suggesting the issue may be tied to sente's design? (not trying to come off as snarky here, or incite trash talkign a lib, just feel like i've been struggling to grasp the proper way to do it every time i try to add a new type of component)

jaen23:02:26

@jjttjj: nah sente's fine, I was talking about compojure. defroutes is a global state, you can't wrap that in a function so you can pass sente as a parameter to close over.

jaen23:02:51

I don't know if compojure supports non-macro route definitions though.

jaen23:02:05

Something like bidi might be a better fit with component.

jaen23:02:56

Though now I look at weavejester's duct and it seems you can use compojure with component somehow

danielsz23:02:00

@jjttjj: If you're not comfortable referring to the system directly, you can do it with dependency injection. There are examples in the system repo.

artiavis23:02:07

Hey guys! I was thinking of introducing a lazy value-based dependency graph for a pure Clojure (not ClojureScript) project. I tried looking around for libraries but only found https://github.com/hoplon/javelin, which appears to be CLJS only, https://github.com/gcv/dgraph, which doesn't seem to be battle-tested or actively maintained, and https://github.com/richhickey/clojure-contrib/blob/master/src/main/clojure/clojure/contrib/dataflow.clj, which doesn't appear to have been migrated over. Are there other libs that do this that I haven't found? Either way, what's a good choice?

artiavis23:02:25

(Must not only support describing transitive dependencies, but must specifically include the Excel-like lazy/caching formula capabilities.)

jaen23:02:39

@jjttjj: But the general idea that seems sensible with component to me is have a protocol like RouteProvider and HandlerProvider that return handlers and routes that then a webserver component can compose together and make a handler out of. You could take a look at juxt's modular for that approach. I think duct is somewhat similar, but I didn't yet have a chance to try it.

jaen23:02:02

@jjttjj: I tried to rip some simplified example from my thesis, maybe it'll help you somewhat - https://gist.github.com/jaen/6d9fdc0819ce662ba24b

artiavis23:02:25

@bfabry: wow this looks pretty interesting

artiavis23:02:27

@bfabry: I'll follow up on the mailing list if I have more questions

gcv23:02:26

@artiavis: I’m the author of dgraph

gcv23:02:38

You’re right that I don’t actively maintain it at the moment, but am happy to talk about it.

gcv23:02:58

FWIW, dgraph does have the lazy and caching semantics you’re describing.

gcv23:02:03

Lack of bugs not guaranteed. 😄

artiavis23:02:19

@gcv: hey! I really liked what I saw, but it has very few downloads on clojars, and you even mentioned on the readme that it has potential bugs with things like threading and mutating the graph on the fly

gcv23:02:09

Yes, I remember discussing it with Rich a few years ago, and he pointed out a potential memory leak. I’d have to spend some time thinking about it to remember the exact scenario that would cause it to happen.

artiavis23:02:18

for the use case I have in mind, I'd need to be able to wire/unwire bits from the graph on the fly

gcv23:02:25

How large a graph?

artiavis23:02:13

For https://github.com/cryogen-project/cryogen-core, so basically for caching the compilation process for very large sites. The graph won't necessarily be very large, but I'd need to be able to leave the graph running and keep adding or removing from it.

artiavis23:02:22

@gcv: out of curiosity, why did you write dgraph instead of using clojure-contrib.dataflow?

gcv23:02:04

IIRC dataflow is destructive.

gcv23:02:28

dgraph is purely persistent in the same way as Clojure maps are (it uses maps under the hood).

gcv23:02:47

I currently think dgraph can be (1) brought up-to-date with modern Clojure, and (2) the leak bug fixed in a few days of work. The trick is finding those few days in my schedule to do that.

artiavis23:02:41

@gcv: I see. I got that dgraph is nondestructive from the examples, but didn't find any samples of dataflow handy from which to compare.

artiavis23:02:17

@gcv: have you seen the plumbing library? at first blush it looks pretty similar in premise but more fleshed-out