Fork me on GitHub
#babashka
<
2022-02-02
>
borkdude22:02:24

bb master was updated to clojure 1.11 beta1.

$ bash <(curl ) --version 0.7.5-SNAPSHOT --dir .

$ ./bb doc iteration
-------------------------
clojure.core/iteration
([step & {:keys [somef vf kf initk], :or {vf identity, kf identity, somef some?, initk nil}}])

🙌 8
Dig22:02:17

already using it with aws-pod for pagination

mmz11:02:11

@U01BDT7622X would be very interested in an example if possible

Dig12:02:27

@U088NU894 here is simple example:

(defn describe-instances
  "Describe instances, returning lazy sequence."
  [ec2]
  (->> (iteration
        (fn [token]
          (aws/invoke ec2 (cond-> {:op :DescribeInstances}
                            token (assoc :request {:nextToken token}))))
        :kf :nextToken
        :vf :Reservations)
       (into [] cat)))

1
1
1
Benjamin15:02:18

used on jvm to iterate sentry events

(defn
  get-api
  [opts]
  (merge
   {:oauth-token (sentry-token)
    :method :get
    :client @sni/default-client}
   (update opts :url get-url)))

(defn
  request!
  [req]
  (let [resp @(client/request req)
        {retry-after :retry_after
         :as body}
        (->
         resp
         :body
         (json/read-str :key-fn keyword))]
    (if
        (not retry-after)
        (assoc resp :body body)
        (do
          (async/<!!
           (async/timeout retry-after))
          (recur req)))))

(defn link->next-cursor-data
  [link]
  (->>
   (str/split link #";")
   (take-last 3)
   (into
    {}
    (comp
     (keep
      #(rest
        (re-find #" (\w+)=\"(.*)\"" %)))
     (map
      (juxt keyword identity))))))

(defn
  iteration*
  [api]
  (eduction
   cat
   (iteration
    (fn step! [cursor]
      (let [req (cond->
                    api
                    cursor
                    (assoc-in
                     [:query-params "cursor"]
                     cursor))]
        (request! req)))
    {:vf :body
     :kf (comp
          (fn
            [{:keys [:results :cursor]}]
            (when
                (= results "true")
                cursor))
          link->next-cursor-data
          :link
          :headers)})))

(defn
  events-iteration
  []
  (iteration*
   (get-api
    {:url (str
           "/projects/"
           (:org.sg.sentry/organisation-slug
            config)
           "/"
           (:org.sg.sentry/project-slug
            config)
           "/events/")
     :query-params {"full" true}})))
bit messy with this link->next-cursor-data parsing the link in the headers but this works well

1