This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # 100-days-of-code (5)
- # announcements (3)
- # beginners (68)
- # cider (2)
- # cljdoc (2)
- # cljs-dev (10)
- # cljsjs (2)
- # clojure (40)
- # clojure-austin (2)
- # clojure-dev (17)
- # clojure-italy (8)
- # clojure-spec (4)
- # clojure-uk (9)
- # clojurebridge (1)
- # clojurescript (48)
- # datomic (4)
- # emacs (4)
- # figwheel-main (93)
- # fulcro (8)
- # hyperfiddle (33)
- # jobs-discuss (3)
- # luminus (60)
- # off-topic (66)
- # onyx (42)
- # pedestal (11)
- # re-frame (35)
- # reagent (1)
- # reitit (39)
- # shadow-cljs (30)
- # specter (27)
As you noticed the cache interfaces are usually too complicated for people to use in such detail, in higher logic code my stuff looks more like memoize "read from cache with this key or invoke that loader function to get it".
we don't iterate over maps by hand when we look up a value for a key, we have a ready made function for us to do that, i don't see why caches should force you to write the if-not-cached-then-load-otherwise-cache-this-and-then-give-me 🙂 that part of the code is pretty universal, there is no point to repeat it everwhere 🙂
@kulminaator For the vast majority of cases, the
through-cache function is sufficient.
core.memoize very heavily at work and we haven't (yet) been bitten by that edge case.
To be honest, if you have sufficient contention that a "Cache Stampede" is possible using the most straightforward idiom with
through-cache) then you're likely to have sufficient contention that the whole cache-in-an-atom approach is going to cause you problems anyway -- and you would need to move to a mutable cache rather than
core.cache's immutable cache approach...
Thanks @seancorfield for looking at that. Indeed, I think that we would hear production horror stories about Clojure itself if atoms where not working in practice.
Are you memoizing things from the db? Commonly used entities? Other things? I’m very curious :)
Yes, and that was the reason for adding the ability to
core.memoize to ignore arguments -- in particular ignoring the DB connection pool argument that is the first one for all the
You have to have a lot of contention before you get retries on
swap! I think. It's definitely a (theoretical) possibility tho'...
Also, TTL caches have the added complexity that a lookup can expire a cache item so a lookup can return
nil and then you have to retry the whole operation.
Can you share some back of the envelope numbers e.g. requests per second on a single server that you are seeing?
I guess results are heavily situation dependent, but some order of magnitude expectations would be nice.
"cache stampede" is more properly addressed not in the caching layer, but by adding a so-called 'circuit breaker' in the function(s) that query the actual database (i.e. the ones which you want to back off during stampede)
this pattern (and more) are documented in this book => https://www.amazon.com/Release-Production-Ready-Software-Pragmatic-Programmers/dp/0978739213
and if you want a java api that does this out of the box, take a look at Hystrix => https://github.com/Netflix/Hystrix
Oh yes, I have this book on my desk but haven’t got around to reading it yet. Good to know @lmergen
hi, I’m trying to create a macro that takes a class and create an object, but if I pass the class as variable to the macro it doesn’t work. I’ve asked a question on stackoverflow here. I understand Macros don’t evaluate arguments like functions but I don’t know how can I fix this . https://stackoverflow.com/questions/52457652/a-macro-that-creates-object-in-clojure/
hey folks, is it possible to just reload a namespace without reloading its dependencies ?
does it mean the repl will recompile all functions in a namespace whenever I save the file?
:) clojure is cool like that. Things like (Repeat), (cycle), (repeatedly) make life easy for me. And I only recently found (interleave) and (interpose)
Not sure if that actually helps with your surrounding code, but it does give youthe repeating behaviour
if you can write your problem in terms of reduce or loop/recur then you dont need state (I dont think)
hmmmm. want to write a macro that adds to the docstring of any forms within. that would amount to adding to the :doc entry in the metadata map, right? Is it just me or does that seem like something that might be more trouble than it's worth?
Is it very very important to you that you can wrap it around forms within? If instead you wrote a function that modified the doc string of a thing defined earlier, that could be implemented as a fairly straightforward function. As a macro wrapped around things, your macro would need to do some kind of scan over the forms and look for things that can have :doc metadata like def, defn, etc.
what if it just assumes everything within can have metadata and I'm fine with it throwing an error if that's not the case?
If you restrict what can be inside to something where "the second symbol of every form is assumed to be the name of something being defined, and could have doc metadata -- the macro checks for doc metadata and if present, modifies it" could work with a pretty simple implementation, I suppose. I was perhaps overcomplicating things by imagining the general case of arbitrary code inside the macro form.