         (update :peer-count dec)
         (update :peer-owners dissoc peer-owner-id))
     state))
+
+(defmethod action :heartbeat [{:keys [heartbeat-fn!] :as state} _]
+  (heartbeat-fn!)
+  state)
 
 (defmethod action :apply-log-entry [{:keys [replica group-state comm peer-config 
                                             vpeers query-server messenger-group] :as state} [type entry]]


(def heartbeat-period-ms 500)

(defn heartbeat! [state]
  ((:heartbeat-fn! state))
  state)

(defn peer-group-manager-loop [state]
  (try 
   (loop [state (action state [:start-peer-group])]

           new-state (cond (= ch shutdown-ch)
                           (action state [:stop-peer-group])
                           (= ch timeout-ch)
                           (action state [:heartbeat])
                           (= ch group-ch)
                           (-> state 
                               (action [:heartbeat])
                               (action entry))
                           ;; log reader threw an exception
                           (and (= ch inbox-ch) (instance? java.lang.Throwable entry))
                           (action state [:restart-peer-group])
                           (= ch inbox-ch)
                           (-> state 
                               (action [:heartbeat]) 
                               (action [:apply-log-entry entry])))] 
       (when (and new-state (not= ch shutdown-ch))
         (recur new-state))))
   (catch Throwable t
