Fork me on GitHub
#admin-announcements
<
2015-12-14
>
markmandel00:12:40

and (refresh-all) doesn't see it either. okay, I am super confused.

markmandel00:12:34

It looks like if I have #?(:clj (:require [clojure.math.numeric-tower :as m])) as the only required thing in the ns, it gets skipped. It's very odd. If I just use (:require [clojure.math.numeric-tower :as m]) without the reader conditional, it works as expected.

nberger02:12:18

@markmandel it seems you are using tools.namespace 0.2.10 but full reader conditionals support landed in tools.namespace 0.2.11

markmandel03:12:21

I'll give that a shot @nberger - although it doesn't explain codox failing

markmandel03:12:47

But maybe? 😕

nberger03:12:18

Codox uses tools.namespace, so yeah, a bit more than maybe :)

boycott10:12:33

hi, I am a javascript developer and the way I build apps is to separate static files to serve straight through nginx, and proxy dynamic pages and json through to an application. I of course know nodejs best, but professionally work in a large financial institution so have learned to know a little scala (but don’t like it), clojure and a tiny bit of haskell. What I want to do is replicate my node app as close as possible in clojure (which I have started using immutant), but to test want to maximise performance to give it as fair a shot as possible, should I stick with jetty or run wildfly, is there a tool to optimise min and max memory for java etc?

robert-stuttaford10:12:10

i recommend you skip immutant and go straight to http-kit

jaen10:12:15

Running immutant in Wildfly will be probably somewhat slower than using immutant-web directly in an uberjar-based application, since it has to conform to servlet specification.

jaen10:12:25

@robert-stuttaford: why?

jaen10:12:38

http-kit is less maintained nowadays

robert-stuttaford10:12:43

ah, i didn’t know that

jaen10:12:45

Not more performant

robert-stuttaford10:12:57

ok. i defer to jaen’s knowledge simple_smile

jaen10:12:58

And only thing it supports that immutant doesn't

jaen10:12:03

Is a http client

jaen10:12:05

That said

artemyarulin10:12:17

https://github.com/ptaoussanis/clojure-web-server-benchmarks here the couple of benchmark results. I think aleph is a good choice

jaen10:12:27

I might be unaware of some of downsides of immutant compared to http-kit

jaen10:12:41

You beat me to that link, heh

jaen10:12:53

Yeah, I agree aleph seems like a good choice as well.

jaen10:12:06

Quite curious how aleph based on undertow instead of netty would compare.

artemyarulin10:12:54

I guess it’s possible to go with bare netty (which I guess 2 times faster than aleph) and use CLJ logic from it somehow

nha10:12:50

Is anyone aware of a Clojure webserver that allow persistent Websocket/SSE/HTTP/HTTP2 connection across code reloads ?

nha10:12:16

(A la Erlang/Elixir)

boycott10:12:28

That techempower test site is great!

nha10:12:54

I played with Compojure/Pedestal/Aleph and now Yada. I am not completely happy with any of those so far by the way.

artemyarulin10:12:38

Does anybody used Rapidoid? According to techempower it’s like 50% faster than netty which is really impressive

nha10:12:38

@artemyarulin: I never heard of it before. Looks impressive !

artemyarulin10:12:22

@nha: Indeed, I’m looking for any docs which describes how they were able to achieve that

nha10:12:31

I am looking for that too right now simple_smile Although I am not sure how representative the techEmpower becnhmarks are (they just make small plain text requests, right ?).

robert-stuttaford10:12:39

it’s all about tradeoffs, though, right? surely the faster ones are sacrificing some capability for speed

robert-stuttaford10:12:33

are the sacrifices worth the speed?

nha10:12:42

My thoughts exactly simple_smile I was expecting Compojure to fare worse than that also, as I though it had a thread per request ?

artemyarulin10:12:46

that’s exactly why I ask - there should be some tradeoff but I couldn’t find it

robert-stuttaford10:12:30

that’s the issue, the benchmarks are concerned only with speed. it’s great that we have them to compare, but it’s not the whole picture

nha10:12:52

Right. I would give a lot of performance away for convenience and predictability.

robert-stuttaford10:12:52

unless, of course, you’re in a game where sheer reqs/sec is a top concern for you

nha10:12:26

The one thing I have been looking for since a long time in a webserver is the ability to reboot without loosing websocket/etc. connections, I have found none so far in JavaLand.

artemyarulin10:12:29

I guess (not sure) it could be resolved with load balanced in the front - so it will maintain all the connections and serve from the different back, while your back instance it rebooting

robert-stuttaford10:12:07

that’s a tough one. the ‘reloaded’ workflow that we like in Clojure is set up to tear everything down and re-instantiate everything, but that’s for dev where it doesn’t matter. i think you’d need something special to prevent long-lived conn drops for production deploys

robert-stuttaford10:12:23

yes, as artemyarulin just said. a facade

robert-stuttaford10:12:15

the Erlang world has this sort of thing totally nailed

robert-stuttaford10:12:25

pretty much because they started there simple_smile

nha10:12:36

Yes, Erlang/Elixir/Phoenix look attractive because of that.

nha11:12:38

In fact I just wrote something on that : https://gist.github.com/nha/618fd914f60ccac94657

robert-stuttaford11:12:51

we serve a websocket app and reboots cull connections. websockets have retry built in, and we have an event-sourced model on the client with a bi-directional, fault-tolerant sync to the servers, so we don’t care if the servers go down or reconnect

nha11:12:16

So cooperation from the client.

nha11:12:50

Seems like the easiest thing is either to move the concern to the architecture then. But I'm not completely happy with that.

robert-stuttaford11:12:15

all depends on the problem you’re trying to solve, i guess

nha11:12:13

Well I've been working on webrtc, chat stuff professionally, those things were missing a lot (was in Node.js/socket io at the time). I'd like to build a pubsub thing in Clojure now, but the availability part is not solved.

robert-stuttaford11:12:20

solving that is a conceptual problem, though. no amount of hijinx with code is going to prevent the fact that your processes are being restarted

robert-stuttaford11:12:31

you’ll need a delegation layer

robert-stuttaford11:12:49

websockets do have retry built-in, so assuming you can do what’s necessary to resume the websocket session on the server when the reconn comes through, you should be ok

robert-stuttaford11:12:11

what does the Erlang world do for down servers on the client? surely they also have a cache and sync system?

robert-stuttaford11:12:17

i am somewhat ignorant on this topic… i’m talking because i want to learn simple_smile

nha11:12:23

Not sure what they do, yes they probably have to do it anyway. But I feel it should go into that situation as little as possible.

nha11:12:46

Well I was planning to do something a la kafka, the client can request it's messages when reconnecting. Although necessary (network problems, server down), it feeld like it should be the last resort.

robert-stuttaford11:12:36

thing is, network is a patchy concept overall these days. mobile network switching or airplane mode, rebooting servers, AWS ELB / DNS issues, they all interrupt that connection. building your system to assume the connection will be sound will give you ulcers. therefore, if you build assuming regular disconnects, you can safely cause regular disconnects, too

robert-stuttaford11:12:19

losing user data sucks, which is why we invested on the client app to cache and sync transparently, retrying until server reports OK for everything

nha11:12:10

Good point. I plan to open this as a service too though, so even if I control the client I would like to avoid this. I am having a look at nginx-clojure, but it lacks a bit of docs, maybe something more heavy can do the trick too, but I would really like to have something that I can fiddle with on a single node.

nha11:12:28

I mean, that seems doable. Not exactly easy but doable.

razum2um12:12:53

could you tell, what’s the bot here (and where is the repo) which keeps track of history in this community?

roelof15:12:24

Does anyone has examples how I can make template inheritance work with hiccup on a reagent project ?

jetmind15:12:02

@roelof: Just compose functions! https://github.com/brain-fn/essence/blob/master/src/essence/handlers.clj#L23-L74 It's not reagent, but hiccup. wrap-page in this case is similar to a base template, which takes additional content as markup parameter and wraps it in all the stuff it needs (header, etc)

roelof15:12:12

oke, but if you have some 20 pages , are the handlers then not get very large

roelof15:12:34

and how do I put these together ?

jetmind15:12:22

depends on the pages you have really. It's not really larger than html based template

jetmind15:12:42

just extract as much as you can into the helper functions for header, footer, menu, whatever else you would have and make a wrapper to serve as a base template (or couple of them if you need)

roelof15:12:44

I try to make this work with hiccup : https://laboutique.lemonstand.com/ and I think it will take some 10 - 15 pages

robert-stuttaford15:12:18

hiccup can collapse lists

robert-stuttaford15:12:43

[:div (for [a [1 2 3]] [:p a])]

roelof15:12:58

@jetmind any example of that sort of wrapper ? Sorry to ask so many questions. Im a beginner in clojure and in web development with clojure

robert-stuttaford15:12:07

(defn page-wrap [& content] (hiccup/html5 [:body content])) (defn page1 [] (page-wrap [:div [:h1 “page 1”]]) (defn page2 [] (page-wrap [:div [:h1 “page 2”]])

robert-stuttaford15:12:50

like that, basically. the trick is to use the & operator to soak up everything passed to page-wrap and let hiccup deal with it as a list

robert-stuttaford15:12:23

this is just one way to do it. once you get that it’s just Clojure data, all the possibilities open up to you simple_smile

jetmind15:12:58

@roelof: see wrap-page function in link I posted above, also look at what @robert-stuttaford told (it's the same principle really)

roelof15:12:01

@robert-stuttaford: that would be a very big function if I do it like this with a lot of code in the bod. Or I misunderstood what you mean

robert-stuttaford15:12:13

try it out, roelof

robert-stuttaford15:12:22

get a feel for it and see

roelof15:12:46

I see it. In my project only the body have to change so I could make a wrap page where a different body is being called.

roelof15:12:47

sorry that I did not see it first. I think I need to take more time to look more carefully at the code

roelof15:12:35

I will experiment with it and hopefully get it working

robert-stuttaford15:12:29

100% simple_smile best way to get familiar with it

robert-stuttaford15:12:41

if you start writing macros, you’ll know you’ve gone too far 😄

roelof15:12:06

@jetmind : is sente easier to learn then react ? I like to make a ecommerce site where I would like that the shopping cart is updated without a browser refresh

jaen15:12:28

Those have entirely nothing in common.

roelof15:12:54

@robert-stuttaford: I have not learned to write very easy macros so that would not be a problem

jaen15:12:01

Sente is a library for writing websockets, more or less.

jaen15:12:12

React is a library for dynamic client-side components.

roelof15:12:35

@jaen: I know but as far as I know both can be used to make real-time web applications

robert-stuttaford15:12:44

you could use sente and react (via reagent or one of the other wrappers) very nicely together

jaen15:12:49

But it solves a different problem.

jaen15:12:01

Sente can talk to your server, but can't display anything

jaen15:12:10

React can display whatever you want, but can't talk to your server

jaen15:12:34

It's a bit like asking if you can use CSS to solve a differential equation, those are totally different things.

roelof15:12:48

oke, so you need both to make a realtime app

jaen15:12:54

Or neither.

jaen15:12:56

For example

jaen15:12:22

Instead of using sente you can use cljs-ajax or cljs-http and just do AJAX calls

jaen15:12:29

That would be enough for a refreshable cart.

jaen15:12:40

No need to go into websockets unless you need two-way communication

jaen15:12:50

Say, you were writing a chat - yeah, sente is great.

jaen15:12:54

In your case that's an overkill.

roelof15:12:17

oke, I think I have a project which is more then I can chew. Many parts that I still have to learn

jaen15:12:33

The same with reagent - you could use a library wrapping jQuery or goog.dom like jayq or domina and don't have to touch React.

jaen15:12:54

Or choose Holpon or freactive or zelkova or any other library that does not depend on React.

jaen15:12:15

It's just that React is the most popular in Clojurescript (and quite so in the wider Javascript world) and for a good reason.

jaen15:12:38

And things like jQuery or goog.dom are just antiquated and don't scale well to more complex applications.

jaen15:12:43

What I suggest you do

jaen15:12:54

Is first write your project as a multi-page application.

jaen15:12:56

Zero javascript

jaen15:12:06

Just posting forms and redirecting to new URLs and so on.

jaen15:12:10

That'll be pretty easy

roelof15:12:12

oke, just plain hiccup

jaen15:12:20

Like you would do with Rails or Sinatra or something else.

jaen15:12:24

When you have that working

jaen15:12:41

You can try using reagent + cljs-ajax to make parts of website interactive, like the cart.

jaen15:12:52

There's nothing stopping you from using reagent on only the part of website

jaen15:12:05

You don't have to go full SPA - you can just have one div reactified.

jaen15:12:25

Step-by-step is the most sensible solution I think.

roelof15:12:34

oke, then the next few days/ 2 weeks making my site work with all the pages I want.

roelof15:12:27

Making the login work / displaying articles / working with a database (first it can be a map in memory)

jaen15:12:42

Yeah, that sounds like a sensible approach

jaen15:12:46

Don't overextend yourself.

roelof15:12:07

that is a problem I have encountered earlier with 4clojure

roelof15:12:25

Trying to make a solution in one step instead of small steps

jaen15:12:56

Yep, bulding up bigger things from smaller is a thing functional programming is good at

jaen15:12:01

So you should try to leverage that.

roelof15:12:19

I try but old habits die not so fast

roelof15:12:05

@jaen: I could start with a compojure or luminus template ?

jaen15:12:38

I never used templates to be honest, I like to setup the project just how I want it, with libraries I like

jaen15:12:40

But in your case

jaen15:12:48

Yeah, Luminus sounds like a good choice to me.

jaen15:12:02

Think somewhere between Sinatra and Padrino in Ruby world.

jaen15:12:17

You get some structure, some libraries and off you go.

sventechie15:12:01

@roelof I’ve worked from Luminus and also from the Immutant demo project and was happy. Luminus is very flexible and well documented.

roelof15:12:35

oke, first step : do some beginners tutorials in luminus

sventechie15:12:28

Yes, further down the road you may want to consider @danielsz system based on @stuartsierra component architecture. That also has ready-made support for immutant and a very clean configuration system.

jaen15:12:14

I think that's far too early. It's just gonna confuse him.

jaen15:12:30

It's better he gets comfortable with Luminus as-is.

roberto15:12:51

yeah, just start with Luminus, don’t pay attention to component or system for now.

roberto15:12:01

they are a little hard to understand for a beginner

jaen15:12:10

Grokking how to do components wasn't all that straightforward for me, never having done any non-trivial system with dependency injection.

roberto15:12:33

I had to dedicate an entire day to just component before I understood it.

roberto15:12:26

it can be a set back for beginners, they should just focus on the basic tools to start with, and component is not a basic tool.

sventechie15:12:27

True. Luminus has started moving that way as well, though, so it might come up.

roelof15:12:49

correct, I did a quick look and saw it nothing for me yet

jaen15:12:29

@sventechie: You sure? Yogthos doesn't seem to like component.

roelof15:12:15

but why not use the compojure template . I could then learn to add my own authentication as friend instead of boddy

jaen15:12:40

Well, to me buddy is considerably simpler.

jaen15:12:55

I couldn't make head or tails out of friend, so I'm not sure if it's a good choice for a beginner.

jaen15:12:13

Don't jump from library to library as much. Take something simple and stick with it.

roelof15:12:16

As far as I can see luminus is using friend

roelof15:12:06

no, im wrong it using bouncer

jaen15:12:27

Bouncer is for form validation, nothing to do with authentication.

jaen15:12:42

And Luminus doesn't really force you to use anything, you can swap things as you wish.

roelof15:12:48

I take a break

jaen15:12:10

But for authentication I think buddy is it's first suggestion - http://www.luminusweb.net/docs/security.md#password_hashing

sventechie15:12:16

@jaen Re: component, not sure yogthos doesn’t seem to hate it: http://yogthos.net/posts/2015-10-01-Compojure-API.html

jaen15:12:16

And I'm behind that - it's simple.

roelof15:12:04

@jaen: you right. I take a break.

roelof15:12:20

too long behind the screen I think

jaen16:12:24

He seems to prefer mount as component seems too OO and complex, and I can get behind that actually.

jaen16:12:29

I myself am eyeing https://github.com/jarohen/bounce right now, mount didn't somehow convince me - I tried it and it started components in the reverse order than I expected for reasons that weren't obvious for me.

jaen16:12:51

Component, while more complex, at least is not surprising in behaviour.

jaen16:12:39

Yoyo by the author of bounce was interesting, but handling monads in Clojure tends to be awkward, so I'm curious what he is planning to do with bounce to alleviate that.

sventechie16:12:05

@jaen Hmm, he has some good points. @danielsz systemisa bit more high-level and is being integrated with `mount` as well~.

jaen16:12:44

But if I understand correctly system is just a collection of components, isn't it?

jaen16:12:45

I tend to prefer write the component myself, feel like I have more control then. But system's boot task for reload is pretty cool, though I had to hack it to add regex-based exclusion.

danielsz16:12:02

Nice, @jaen ! If you think it can be useful to others, please feel free to push a PR.

jaen16:12:20

@danielsz: but that's only boot-specific, I wouldn't know how to do it for lein.

jaen16:12:45

Okay, I guess I can push a PR for that in a moment.

jaen16:12:34

Nie ma za co ; d

jarohen16:12:33

hi @jaen - yes, monads in Clojure did turn out to be pretty awkward

jarohen16:12:34

I'm working on a readme for bounce at the moment, (on the readme branch on GH), but most of the docstrings are in place, and some tests too

jaen16:12:59

Well, that depends, I implemented event sourcing event application as fold over maybes and it was pretty cool and not all that verbose, but when I tried to grok yoyo I was a bit at loss.

jaen16:12:12

Component is cool and all, but it's OO-centric approach feels a bit weird.

jaen16:12:58

I liked that you could just ask the dependency out of the monad without having to pass things around or write methods on records (at least that's how I understood it, maybe I'm wrong here)

jarohen16:12:40

mm, agreed - it's a great idea to set out your application state in the Component way, but it was that OO-ish approach that caused me to start looking around for alternative solutions - mostly just variations on a Component theme, though

jarohen16:12:52

yep, that's right

jarohen16:12:16

although it's viral - every time your callee needs to return a monadic value, you yourself need to as well

jarohen16:12:22

which didn't work out so well in practice

jaen16:12:16

Yeah, I can imagine how it's cleaner in Haskell for example, but I'm no walking typeclassopedia at the moment so I'm taking a stop at Clojure. Monads are cool and all, but if you can be sideeffectful like in Clojure that can be an unneeded burden, I guess.

jaen16:12:53

If bounce has something like that, that is being able to set up a system, and ask for dependencies without passing arguments around it could be pretty cool.

jaen16:12:25

Does it resolve dependencies a la component, or will it need explicit ordering like with leaven?

jarohen16:12:18

so bounce is completely monad-less - which should get around a lot of the problems of yoyo

jarohen16:12:43

but yes, resolves dependencies like component - you give it a map of dependencies and it resolves them

jarohen16:12:59

(it uses Stuart Sierra's 'dependency' library under the hood, same as Component)

jarohen16:12:40

difference is that I'm looking into ways that you don't have to: - pass the whole system around everywhere - but keep the referential transparency related test benefits

jarohen16:12:01

very much in progress at the moment though, so completely subject to change! simple_smile

jaen16:12:06

That sounds nice.

jaredly16:12:07

Is there an easy “transform a hash-map by mapping over the values”? Right now I’m doing (apply hash-map (mapcat #(list (first %) (dothing (second %))) my-hash-map)) which isn’t super elegant

jaen16:12:35

@jarohen: Any thoughts about co-dependencies?

jarohen16:12:46

@jaredly: I tend to use map-vals from @weavejester's 'medley'

bronsa16:12:48

@jaredly: there are a number of util libraries that implement that, usually called update-vals or map-vals

jaen16:12:50

I usually use clojure.walk, didn't know about those libs.

jarohen16:12:06

@jaen: trying to avoid them where possible! cyclic dependencies can usually be refactored away

jaen16:12:25

@jarohen: that is a fair point, but what happens if you can't?

yogthos16:12:26

@jaen: wrt mount, the starting and stopping of states is based on the namespace hiearchy

yogthos16:12:46

so the components should be started in order they’re required in

yogthos16:12:10

and as a side effect if a namespace is not used anywhere then its state will not be part of the lifecycle

yogthos16:12:41

the latest version also works with cljs now, so you can mange stuff like websocket connections with it

jaen16:12:13

So if I understand correctly I have to manually make sure it is required like so?

[component.depdency]
[component.dependent]

jaen16:12:40

I tried to make a component that depended on another component and couldn't seem to have them start in the right order for some reason '

yogthos16:12:43

well let’s say you have two states a queue and a database, and the queue state has to be started before the database state

jarohen16:12:48

@jaen: that's a fair point too simple_smile tbh, I've never come across a situation where you couldn't, so it hasn't been enough of an issue - example and/or PR gratefully received though simple_smile

yogthos16:12:37

so you might have namespaces like app.queue that has its defstate for the queue and app.db with a defstate for the db connection

yogthos16:12:04

if app.db requires app.queue, then the queue state will be started before the db one

yogthos16:12:37

I’ve switched a few apps I’m using to mount and I found I generally don’t have to think about this explicitly

yogthos16:12:37

the start/stop order will be dictated by the namespace hierarchy, and since namespaces that rely on a particular state will have to require namespaces that manage it then it forces the states to be started in that order

jaen16:12:57

Yeah, I figured so, that's why them starting in reverse surprised me, maybe I've just misunderstood something.

jaen16:12:27

Anyway, not having to lug around the system and/or write OO-ish records mount and bounce give seems like a nice thing.

yogthos16:12:41

yeah I think the big difference with mount is that it leverages namespace declarations, while other systems introduce an additional layer like classes

jaen16:12:36

I actually like explicit system map for some reason, but I can see the appeal of that. Not having to do records is the biggest win I think.

yogthos16:12:38

note that mount can generate the resulting system

yogthos16:12:13

for me the biggest win is that I can have completely self contained component namespaces

sveri16:12:14

Actually I think I will replace component by mount too in closp when I have time to do so. I think it has a better readability than component in a clojure namespace.

yogthos16:12:52

my main issue with having a global system is that it has to be passed all over the app

jaen16:12:28

@yogthos: well, component namespaces are also self contained to be pedantic, if you use record you can close over it's fields and you don't have to worry about the implementation detail of having to carry the system about.

jaen16:12:36

But then you have weird OO-ish record code.

jaen16:12:40

Which is meh to read.

yogthos16:12:48

but the context has to be passed in from the top

jaen16:12:15

Yeah, but you don't have to do that, component does that for you.

jaen16:12:24

If I understand it correctly.

yogthos16:12:56

you generally would pass the config from the top level the way duct does for example

jaen16:12:38

The problem is you either have to have methods in a record to close over the fields as to not have to get things from the system, or you have methods outside the record at the cost of having to get the system components you need from the param.

jaen16:12:55

And either is awkward to be honest.

roelof16:12:02

one luminus question : what does this do <a href="{{servlet-context}}/about">About</a> expecially the servlet part

yogthos16:12:27

it’s for running on app servers like tomcat

yogthos16:12:39

if you’re running standalone then the context will always be empty

yogthos16:12:58

but if you deploy to an app server then each app has to have a unique context for routing

roelof17:12:35

oke, so I can better make all my links that way when using the luminus template ?

yogthos17:12:32

only if you plan on running on an app server

yogthos17:12:24

if you’re just going to make an uberjar then you can just omit that

yogthos17:12:53

another case could be if you front multiple apps with apache/nginx and you don’t want to setup subdomains

roelof17:12:04

maybe one time. It's not a hobby-project in my mind but maybe later on I could decide to deploy it

roelof17:12:07

now time for dinner

roelof17:12:19

Thanks everyone for the time and patience

mlbatema19:12:41

@nha, @robert-stuttaford: Erlang's persistence of connections over code reloads doesn't involve a process or server going down. A client reaching a unresponsive system is the same in Erlang as it is in Clojure simple_smile

robert-stuttaford19:12:03

-grin- i suspected as much

mlbatema19:12:30

It's closer to redefining a Var in a running system

robert-stuttaford19:12:53

which we can definitely do in Clojure

mlbatema19:12:53

exactly. Both Clojure and Erlang make no guarantees about how the state may or may not play well with that new code. Erlang just has the convenience layer in it's runtime VM to say "Given a collection of new namespaces, update all the root vars accordingly."

robert-stuttaford19:12:22

yeah. we have to use the reloaded pattern to accomplish that, which is totally ok

mlbatema19:12:08

ah, yeah, I see that. That's pretty cool simple_smile

nha19:12:16

@mlbatema: Thanks for the info ! So it means that it is totally ok for requests which are stateless, but what about websockets and such ? As I understand it you have to keep some state on the server. Does that mean that even Erlang can't do it ?

mlbatema19:12:25

An Erlang hot-code reload can be stateful. You just need be aware of, and implement, potential code-upgrade paths to make your new code work with your old state when incompatible. However, the whole system stays alive during this reload, so there is no downtime.

nha19:12:46

I see, like serializing/deserializing requests? And does the typical Erlang webserver helps with that ?

nha19:12:51

Ok reading your link simple_smile

mlbatema19:12:26

but Sierra's reloaded pattern looks like it can do enough of that. Just put your runtime state into your defined "system" and figure how you'll want to persist that with the start/stop (serialization, dirty global state, whatever)

mlbatema19:12:54

@nha: Webserver has nothing to do with it. All VM-level support.

mlbatema19:12:08

Honestly, hot-code reloads can be complex and can fail. It's a feature you use because it's cheaper to write and test an upgrade path of a live application (or trust a framework to manage as much of it as it can for you) than to accept the downtime necessary to turn off v1 and power on v2.

robert-stuttaford19:12:19

if you keep your websocket connections in an atom (or whatever -waves hands-) outside of the stuff the reloaded workflow manages, then you can do this

robert-stuttaford19:12:15

yeah, mlbatema. like we were discussing earlier, we’ve allowed for the webserver to be completely down by teaching the client how to cache and sync. more work, but affords us more flexibility

mlbatema20:12:14

yeah, that seems the simpler answer. To my knowledge, Erlang doesn't have a solution for the client when the server's completely down. Gotta write/implement all that yourself. Go make friends with CRDTs and read about the CAP theorem 😛

sveri20:12:43

I just tried clj-http and it seems like a failed request in the sense of not being authorized, throws an exception, which is suprising at least. Shouldn't it just return the response from the request and let me handle errors? That's what I would expect. Am I using it wrong?

markmandel20:12:38

@nberger: Updating tools.namespace totally fixed that issue! Much appreciated!

sveri20:12:29

Nevermind, I just found about {:throw-exceptions false}

jaen20:12:45

@sveri: just keep in mind it will stop it only from throwing status code exceptions. Things like timeouts will still throw.

sveri20:12:24

@jaen: ok, thank you, that is perfectly fine. Was just surprised, from a clients point of view I think, 401 or 403 are perfectly valid responses simple_smile

jaen20:12:47

Yeah, I agree

nberger20:12:45

Nice to hear @markmandel!

joshua.d.horwitz22:12:20

Hi everyone, new to Clojure and hoping to make a website for a friends nonprofit using it