(ns jepsen.antietcd.set
  (:require
    [jepsen
      [checker :as checker]
      [client :as client]
      [generator :as gen]
    ]
    [jepsen.antietcd.client :as anticli]
    [clojure.data.json :as json]
  )
)

(defn r [] {:type :invoke, :f :read, :value nil})
(defn w [] (->> (range) (map (fn [x] {:type :invoke, :f :add, :value x}))))

(defrecord SetClient [k url]
  client/Client
  (open! [this test node] (assoc this :url (anticli/node-url node)))

  (setup! [this test] (anticli/throw #(anticli/antietcd_put url k [])))

  (invoke! [this test op]
    (case (:f op)
      :read (merge op (let
        [res (anticli/retry_all #(anticli/antietcd_request (str url "/v3/kv/range") {"key" k}))]
        (case (:type res)
          :ok {:type :ok, :value (if (:kvs (:body res)) (set (:value (first (:kvs (:body res)))))) }
          res
        )
      ))
      :add (merge op (anticli/retry_all #(anticli/antietcd_update url k (fn [x] (vec (conj x (:value op)))))))
    )
  )

  (teardown! [this test])

  (close! [_ test])
)

(defn workload
  "A generator, client, and checker for a set test."
  [opts]
  {
    :client    (SetClient. "a-set" nil)
    :checker   (checker/set-full {:linearizable? true})
    :generator (gen/reserve 5 (repeat (r)) (w))
    :final-generator (gen/once r)
  }
)
