 (ns fault.patterns
-  (:require [fault.core :as core])
-  (:import (fault ServiceExecutor RejectedActionException)))
+  (:require [fault.core :as core]
+            [fault.future :as future])
+  (:import (fault ServiceExecutor
+                  RejectedActionException
+                  MultipleWriterResilientPromise
+                  ResilientPromise
+                  ResilientAction ResilientFuture)))
 
 (set! *warn-on-reflection* true)
+
+(defn- wrap-in-action [fn]
+  (reify ResilientAction
+    (run [_] (fn))))
 
 (defn- next-idx [last-idx current]
   (if (<= last-idx current)

(defn submit-load-balanced-action [load-balancer key->fn timeout-millis]
  (some (fn [[key {:keys [service]}]]
          (try (core/submit-action ^ServiceExecutor service
                                   (get key->fn key)
                                   timeout-millis)
               (catch RejectedActionException _ nil)))
        (load-balancer)))

(defn perform-load-balanced-action [load-balancer key->fn]
  (some (fn [[key {:keys [service]}]]
          (try (core/perform-action service (get key->fn key))
               (catch RejectedActionException _ nil)))
        (load-balancer)))


                     (repeatedly rand-fn)))))))

(defn submit-shotgun-actions [shotgun key->fn timeout-millis]
  (let [^ResilientPromise promise (MultipleWriterResilientPromise.)]
    (doseq [[key {:keys [service]}] (shotgun)]
      (.submitAction ^ServiceExecutor service
                     (wrap-in-action (get key->fn key))
                     promise
                     timeout-millis))
    (future/->CLJResilientFuture promise)))