Skip to content

Instantly share code, notes, and snippets.

@rafaelcorreiapoli
Created November 6, 2017 16:35
Show Gist options
  • Save rafaelcorreiapoli/7eabe146038b513eb35dbb1c3fe2abe5 to your computer and use it in GitHub Desktop.
Save rafaelcorreiapoli/7eabe146038b513eb35dbb1c3fe2abe5 to your computer and use it in GitHub Desktop.
(ns dataloader.dataloader
(:refer-clojure :exclude [load flush])
(:require [graphql-facade.db.monger :refer [db find-all]]
[monger.operators :refer [$in]]))
(defprotocol Loader
(load [this key])
(flush [this]))
(def log clojure.pprint/pprint)
(defn conj-vector-to-set
[s v]
(apply (partial conj s) v))
(defn create-vector
[k]
(if (vector? k) k (vector k)))
(defn extract-correct-values-from-batch
[batch-result keys]
(if (vector? keys)
(map #(get batch-result %) keys)
(get batch-result keys)))
(defn create-promise-with-meta-keys
[key-or-keys]
(with-meta (promise) {:key-or-keys key-or-keys}))
(defn extract-meta-keys-from-promise
[promise]
(:key-or-keys (meta promise)))
(defn extract-pending-from-promises
[promises]
(reduce #(conj-vector-to-set %1 (create-vector (extract-meta-keys-from-promise %2))) #{} promises))
(defrecord DataLoader [batch-fn state]
Loader
(load [this key-or-keys]
(let [my-promise (create-promise-with-meta-keys key-or-keys)]
(swap! state update :promises conj my-promise)
my-promise))
(flush [this]
(let [promises-to-deliver (get @state :promises)
pending (extract-pending-from-promises promises-to-deliver)
batch-result (batch-fn pending)]
(doseq [my-promise promises-to-deliver]
(deliver my-promise (extract-correct-values-from-batch batch-result (extract-meta-keys-from-promise my-promise))))
(swap! state assoc :promises []))))
(defn new-dataloader
[batch-fn]
(map->DataLoader {:batch-fn batch-fn :state (atom {})}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment