aphyr/riemann — pull request #256 by jeroenvandijk (2013-08-23 18:48:10+00:00)
Title: Concurrency fix for example in "Count number of hosts by application gro...

Note: that this fix is an hypothetically one. I haven't seen it go wrong (yet), but I do think that this is an improvement.

When the previous code was called concurrently old values might be applied instead of changing the value atomically.

I can not easily proof that there is a concurrency issue here, but I'll try to explain. The atom is deref outside of the swap! function (old value), now suppose the another thread updates this atom before this swap! is called. When this swap! is called it will apply an old value.

Here is code that shows that, apart from the concurrency issue, the new code is equal to the old one

```clojure
(let [hosts (atom {})
hosts2 (atom {})
tag-str :foo
event1 {:host "baz"}
event2 {:host "bar"}
]
;; This example doesn't work well in concurrent context as it will use an old value of hosts
(swap! hosts assoc tag-str (conj (tag-str @hosts #{}) (:host event1)))
(swap! hosts assoc tag-str (conj (tag-str @hosts #{}) (:host event2)))

;; This one will use always the exact value as the lookup is in a transaction
(swap! hosts2 update-in [tag-str] (fn [h] (conj (or h #{}) (:host event1))))
(swap! hosts2 update-in [tag-str] (fn [h] (conj (or h #{}) (:host event2))))

(= @hosts @hosts2)
)
```