                                                       :my-range ["0" "1"]}]
                                           :attrs []}}))
 
-;; TODO Add loops+merging for :unprocessed-keys (meta) and :unprocessed-items
-
-;; BatchGetItem will return a partial result if the response size limit is
-;; exceeded, the table's provisioned throughput is exceeded, or an internal
-;; processing failure occurs. If a partial result is returned, the operation
-;; returns a value for UnprocessedKeys . You can use this value to retry the
-;; operation starting with the next item to get.
-
-;; * The UnprocessedKeys value is in the same form as RequestItems, so the value
-;; can be provided directly to a subsequent BatchGetItem operation. For more
-;; information, see RequestItems in the Request Parameters section.
-
-;; Typically, you would call BatchWriteItem in a loop. Each iteration would
-;; check for unprocessed items and submit a new BatchWriteItem request with
-;; those unprocessed items until all items have been processed.
+(defn- merge-unprocessed
+  [creds more-f last-result]
+  (loop [{:keys [items unprocessed consumed-capacity]} last-result]
+    (when (seq unprocessed) (println "REPROCESSING!: " unprocessed))
+    (if-not (seq unprocessed)
+      (if items
+        (with-meta items {:consumed-capacity consumed-capacity})
+        last-result)
+
+      (let [{items* :items unprocessed* :unprocessed
+             consumed-capacity* :consumed-capacity}
+            (more-f creds unprocessed)]
+
+        (recur (merge {:unprocessed       unprocessed*
+                       :consumed-capacity (when consumed-capacity
+                                            (+ consumed-capacity
+                                               consumed-capacity*))}
+                      (when (or items items*)
+                        {:items (into (or items []) items*)})))))))
+
+(defn- batch-get-item* [creds raw-request]
+  (merge-unprocessed creds batch-get-item*
+   (as-map
+    (.batchGetItem (db-client creds)
+      (doto (BatchGetItemRequest.) ; {table-str KeysAndAttributes}
+        (.setRequestItems raw-request))))))
 
 (defn batch-get-item
   "Retrieves a batch of items in a single request.

                       {:user-id 2 :username \"jane\"}]
              :delete [{:user-id [3 4 5]}]}})"
  [creds requests]
  (as-map
    (.batchWriteItem (db-client creds)
      (doto (BatchWriteItemRequest.)
        (.setRequestItems
         (utils/name-map
          ;; {<table> <table-reqs> ...} -> {<table> [WriteRequest ...] ...}
          (fn [table-request]
            (reduce into []
             (for [action (keys table-request)
                   :let [items (attr-multi-vs (table-request action))]]
               (mapv (partial write-request action) items))))
          requests))))))

;;;; API - queries & scans


     :friends {:prim-kvs [{:catagory \"favorites\" :id [1 2 3]}
                          {:catagory \"recent\"    :id [7 8 9]}]}})"
  [creds requests]
  (batch-get-item* creds (batch-request-items requests)))

(comment
  (def bigval (.getBytes (apply str (range 14000))))
  (defn- ids [from to] (for [n (range from to)] {:id n :name bigval}))
  (batch-write-item creds {:faraday.tests.main {:put (ids 0 5)}})
  (batch-get-item   creds {:faraday.tests.main {:prim-kvs {:id (range 3)}}}))

(defn- write-request [action item]
  (case action
    :put    (doto (WriteRequest.) (.setPutRequest    (doto (PutRequest.)    (.setItem item))))
    :delete (doto (WriteRequest.) (.setDeleteRequest (doto (DeleteRequest.) (.setKey  item))))))

(defn- batch-write-item*
  [creds raw-request]
  (merge-unprocessed creds batch-write-item*
   (as-map
    (.batchWriteItem (db-client creds)
      (doto (BatchWriteItemRequest.)
        (.setRequestItems raw-request))))))

(defn batch-write-item
  "Executes a batch of Puts and/or Deletes in a single request.
