Skip to content

Instantly share code, notes, and snippets.

@miguelbermudez
Created February 7, 2020 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miguelbermudez/10a4f2bcb2d6fe457a6d4a87e9384176 to your computer and use it in GitHub Desktop.
Save miguelbermudez/10a4f2bcb2d6fe457a6d4a87e9384176 to your computer and use it in GitHub Desktop.
Lacinia Async Example
;; file edited for brevity
(ns ex.graphql.schema
(:require [com.walmartlabs.lacinia.schema :as schema]
[com.walmartlabs.lacinia.parser.schema :as parser]
[com.walmartlabs.lacinia.util :as util]
[com.walmartlabs.lacinia.resolve :as resolve]
[com.stuartsierra.component :as component]
[clojure.java.io :as io]
[clojure.edn :as edn]
[clojure.tools.logging :as log]
[clj-http.client :refer [post]]
[cheshire.core :refer [generate-string]]))
;; Load schemas from EDN
(defn ^:private load-edn [filename]
(-> (io/resource filename)
slurp
edn/read-string))
;;-----------------------------------------------------------------------------
;; Resolvers
;;-----------------------------------------------------------------------------
(defn ^:private prop-resolver
[prop-value]
(fn [context args value]
(get value prop-value)))
(defn ^:private do-req
[config options]
(let [{:keys [api-url]} (:data config)
{:keys [path body selector auth-header]} options
url (str api-url path)
headers (if auth-header
{"Authorization" auth-header}
{})
body-json-str (generate-string body)
selector-fn (or selector #(-> % :body))]
(-> (post url (ddp-req-options {:body body-json-str
:headers headers}))
selector-fn)))
(defn lookup-patient
[config]
(fn [context args value]
(let [{:keys [id]} args
promise (resolve/resolve-promise)]
(.start (Thread.
#(try (resolve/deliver! promise (-> (do-req config {:path "some/path"
:body {:id id}
:auth-header (get-in context [:request :headers "authorization"] nil)
:selector (fn [resp-body]
(-> resp-body :body (get "data") first))})
(resolve/with-context {:id id})))
(catch Throwable t (resolve/deliver! promise nil
{:message (str "Exception: " (.getMessage t))})))))
promise)))
(defn surgery-for-patient [config]
(fn [context _ parent]
(let [{:keys [:id]} context
promise (resolve/resolve-promise)]
(println parent)
(.start (Thread.
#(try (resolve/deliver! promise (do-req config {:path "some/path"
:body {:somekey foo}
:auth-header (get-in context [:request :headers "authorization"] nil)
:selector (fn [resp-body]
(-> resp-body :body (get "data")))}))
(catch Throwable t
(resolve/deliver! promise nil
{:message (str "Exception: " (.getMessage t))})))))
promise)))
(defn pathology-for-patient [config]
(fn [context _ _]
(let [{:keys [id]} context
promise (resolve/resolve-promise)]
(.start (Thread.
#(try (resolve/deliver! promise (do-req config {:path "some/path"
:body {:somekey foo}
:auth-header (get-in context [:request :headers "authorization"] nil)
:selector (fn [resp-body]
(-> resp-body :body (get "data")))}))
(catch Throwable t
(resolve/deliver! promise nil
{:message (str "Exception: " (.getMessage t))})))))))
promise)
(defn resolver-map
"Graphql Resolvers"
[component]
(let [config (:config component)]
{ :prop prop-resolver
:patient/surgery (surgery-for-patient config)
:patient/pathology (pathology-for-patient config)
:query/patient (lookup-patient config)}))
{:objects
{:Surgery
{:description "Surgery Item"
:fields {:procedureDate {:type (non-null String)
:description "Procedure Date"
:resolve [:prop "Procedure Date"]}}}}
:Patient
{:description "A MSK Patient."
:fields {:bmi {:type (non-null String)
:description "Body Mass Index"
:resolve [:prop "BMI"]}
:surgery {:type (list :Surgery)
:description "Surgeries performed on patient."
:resolve :patient/surgery}
:pathology {:type (list :Pathology)
:description "Patient's Pathology events."
:resolve :patient/pathology}}}}
:queries
{:patient
{:type :Patient
:description "Lookup patient by id."
:args {:id {:type (non-null ID)}}
:resolve :query/patient}}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment