 (def channel-hub (atom {}))
 
 (defn broadcast [data]
+  "Broadcast message to all channels and return message hash."
   (let [message (str "data: " (generate-string data) "\n\n")]
     (doseq [channel (keys @channel-hub)]
-      (send! channel message false))))
+      (send! channel message false))
+    (hash data)))
+
+;; Swarm scoped events are received from each manager, but
+;; we want broadcast to FE only once to prevent duplicity.
+;; Therefore we cache event message hash for 1 second.
+(def broadcast-memo (memo/ttl broadcast :ttl/threshold 1000))
 
 (defmethod dispatch :events [_]
   (fn [{:keys [query-params] :as request}]

(ns swarmpit.handler-events
  (:require [org.httpkit.server :refer [run-server with-channel on-close send! close]]
            [clojure.walk :refer [keywordize-keys]]
            [cheshire.core :refer [generate-string]]
            [immutant.scheduling :refer :all]
            [swarmpit.slt :as slt]

  (fn [{:keys [params]}]
    (if (some? params)
      (do
        (broadcast-memo params)
        (resp-accepted (str "Broadcasted to " (count @channel-hub) " clients")))
      (resp-error 400 "No data sent"))))