This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-11-20
Channels
- # announcements (2)
- # architecture (5)
- # beginners (118)
- # cider (5)
- # clara (13)
- # cljdoc (8)
- # cljs-dev (49)
- # cljsjs (2)
- # clojure (107)
- # clojure-dev (9)
- # clojure-europe (3)
- # clojure-italy (58)
- # clojure-japan (2)
- # clojure-nl (6)
- # clojure-spec (89)
- # clojure-uk (27)
- # clojurescript (9)
- # core-async (33)
- # cursive (2)
- # datascript (2)
- # datomic (31)
- # duct (4)
- # emacs (1)
- # events (1)
- # figwheel-main (1)
- # fulcro (69)
- # hoplon (7)
- # hyperfiddle (16)
- # incanter (4)
- # instaparse (4)
- # kaocha (1)
- # mount (2)
- # nrepl (19)
- # off-topic (40)
- # onyx (6)
- # other-languages (3)
- # pedestal (2)
- # re-frame (48)
- # reagent (2)
- # reitit (10)
- # ring-swagger (9)
- # shadow-cljs (63)
- # spacemacs (13)
- # sql (8)
@cureadvocate there may be others, but I think https://github.com/clojure/math.numeric-tower has functions that deal nicely with the various numeric types
ty, jaawerth. I didn't think that worked for BigInteger, but it does. Yay!
Is it possible to find out if a value is serializable? Like is there an interface/protocol serializable values implement?
What do you mean by serializable?
Java has a Serializable interface but not sure if that’s actually what you want
@alexmiller encodable to transit-json
thanks for responding!
@jesse.wertheim There's some hidden gems under the clojure/ umbrella, that I think would benefit from more publicity. Like data.avl, data.priority-map, core.memoize, algo.generic, math.combinatronics, core.match, etc.
@didbus I believe I once found a low level method to get the current address/pointer to an object in Java, but realize that such a value can change on every GC, and the times of GCs are unpredictable.
It looks like I experimented a few years ago briefly with a library called jol for "Java Object Layout" here: https://openjdk.java.net/projects/code-tools/jol/ It has a method VMSupport/addressOf that can return the current address of an object, after doing (:import (org.openjdk.jol.util VMSupport))
. Note: I do not all the possible caveats of this method or what all might go wrong with it, but there is at least the issue that the value can change on every GC.
I don’t know if there is a straight way to do it, but this should work:
(set! *data-readers* (into *data-readers* (map (fn [[tag f]] [tag (resolve f)])) (read-string (slurp ( "data_readers.clj")))))
Trying this example from https://clojuredocs.org/clojure.core/re-groups
(def phone-number "")
(def matcher (re-matcher #"((\d+)-(\d+))" phone-number))
(re-groups matcher)
According to the example it gives ["672-345" "672-345" "672" "345"]
but I get:
Execution error (IllegalStateException) at java.util.regex.Matcher/group (Matcher.java:536).
I get same error with Clojure 1.9.0 and JDK 1.8.0_192. Not clear to me yet whether that ever worked, or is changed behavior.
user=> (doc re-matcher)
-------------------------
clojure.core/re-matcher
([re s])
Returns an instance of java.util.regex.Matcher, for use, e.g. in
re-find.
Doubtful. More likely that the example never worked
^^ designed for use with re-find
user=> (re-find matcher)
["456-3212" "456-3212" "456" "3212"]
@borkdude Interested in correcting the example on http://ClojureDocs.org?
then after that, you can:
user=> (re-groups matcher)
["456-3212" "456-3212" "456" "3212"]
but it requires you to have previously called re-find, yes
Java Matcher objects are mutable.
so call sequence is important.
ClojureScript regex's probably have some way to get multiple "capture" substrings from a single regex match, or at least most regex libraries nowadays do, but I haven't looked. Just surprised if it doesn't enable that functionality.
you may have heard that mutable objects are bad :)
make a table of tradeoffs 🙂
yeah. I’m writing a spec for re-groups now, that’s why I bumped into this. never actually used it
@andy.fingerhut interestingly via writing a spec for subs, I got into this: https://dev.clojure.org/jira/browse/CLJS-2979
Is that ClojureScript-specific behavior, perhaps?
Just checked that Clojure/JVM throws exception on (subs "" 1)
as I would have expected, although the exception message contains -1
instead of 1
which is a bit weird, but at least the exception is there.
Simultaneous fix + speedup for the win!
Does it make much sense to write a spec that checks return values of functions that take and modify mutable objects? I would guess that would be fraught with trouble.
good or bad: function/var names with :
? ex: find-thing:source-a
find-thing:source-b
(no I don't want/need to use a multimethod, it's just a naming thing here)
I didn’t say it was invalid
> Symbols beginning or ending with ':' are reserved by Clojure. A symbol can contain one or more non-repeating ':'s.
I just don’t like it
You asked good/bad :)
Not valid/invalid
yay, I can now see the return “type”:
user=> (doc re-groups)
-------------------------
clojure.core/re-groups
([m])
Returns the groups from the most recent match/find. If there are no
nested groups, returns a string of the entire match. If there are
nested groups, returns a vector of the groups, the first element
being the entire match.
Spec
args: (cat :matcher :speculative.specs/matcher)
ret: (or :string :speculative.specs/string :seqable :speculative.specs/seqable-of-string)
nil
hm lein uberjar
seems to completely ignore that some dependencies are marked as scope "compile"
or "provided"
is this clojure artifacts that are in compile / provided scope while doing aot / gen-class ?
because that could lead to a situation where the source jar for the clojure code isn't in the uberjar, but the compiled result of the dep is - aot is transitive
I'm curious to learn more about deploying a single-process Clojure app with zero downtime. Not sure if that qualifies as blue-green deployment but something in that direction. Are there any tools to make this easy? How did you solve this?
if you're insane you could use tools.namespace/refresh and hot load the new code in the prod process
@U050TNB9F fwiw, we do this on the JUXT website...
and this works out for you?
I think the real answer is usually some variant of load-balancing and service discovery
which would not be different between clojure and another language as I understand it?
Normally you have a fleet of hosts, and you rotate them in and out as new changes are deployed
I was thinking that perhaps there's something particularly easy to setup. Currently I'm just running a systemd process and nginx reverse proxying to a hardcoded port.... so service discovery and swapping processes sounds like it'll require a lot more components...
right - to limit downtime you need multiple processes (at least for a minute or two at a time)
and then load balancing or service discovery to make the swap seamless
> Normally you have a fleet of hosts, and you rotate them in and out as new changes are deployed Yeah, that particular app doesn't follow an "immutable infrastructure" style approach where you just cycle entire nodes (the node is stateful)
Right multiple processes for the transition time would be expected.
I think this is part of why people end up using things like redis and kafka - to pull the stateful stuff out of the apps
at @dayjob we use kafka to accumulate runtime state, then marathon to manage app instances, and the kafka topics are a mechanism of service discovery of sorts
disk persistence
Yeah, definitely agree with the general motivation of having state in separate services but the project is OSS and I want to keep setup as easy as possible in the interest of contributors (using SQLite at this time)
Ok, well, you can probably pull it off if you can dynamically change the nginx port. You could start a new process on a different port and then do the port swap, and then kill the old process.
what about abstracting the sql layer, so people can use eg. postgres for seamless roll over, or sqlite for simplicity?
yeah this would be an option but not managing a DB process is also nice and something I guess I'm still reluctant to give up
docker does tend to make this stuff easier - but that has some things you need to opt in to of course...
you might also look at something like envoy, likely overkill but I suspect doing the swap in envoy would be easier than in nginx
have a link to envoy? I assume you don't mean amperity/envoy?
> NGINX configuration is captured in configuration files. When you change a configuration file and restart NGINX to pick up the new configuration, it implements a “graceful restart”. Both the old and new copies of NGINX run side by side for a short period of time. The old processes don’t accept any new connections and terminate once all their existing connections terminate.
oh - so you could roll over nginx with an alternate port config
I'm also looking at Caddy which seems like a nice reverse proxy with automatic HTTPS: https://caddyserver.com/docs/proxy
It supports an upstream
option that can be a port range...
> try_duration is how long to try selecting available upstream hosts for each request. By default, this retry is disabled ("0s"). Clients may hang for this long while the proxy tries to find an available upstream host. This value is only used if a request to the initially-selected upstream host fails.
This could also be interesting https://stackoverflow.com/a/32001397/172272
I did, thanks for your suggestions 🙂