Skip to content

Commit

Permalink
got rid of Tufte dep + various improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Valentin Waeselynck committed Oct 12, 2018
1 parent 65f372c commit cd62f27
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 247 deletions.
2 changes: 1 addition & 1 deletion deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{org.clojure/clojure {:mvn/version "1.8.0"}
manifold {:mvn/version "0.1.6"}

com.taoensso/tufte {:mvn/version "1.4.0"} ;; FIXME
;com.taoensso/tufte {:mvn/version "1.4.0"}
}
:aliases
{:dev
Expand Down
7 changes: 2 additions & 5 deletions src/d2q/api.clj
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
(ns d2q.api
"Demand-driven querying à la GraphQL / Datomic Pull"
(:require [clojure.walk]
[manifold.deferred :as mfd]
[d2q.impl.utils :as impl.utils]
(:require [manifold.deferred :as mfd]
[d2q.impl]
[d2q.datatypes])
(:import (java.util ArrayList)))
[d2q.datatypes]))

;; TODO improvements (Val, 15 Mar 2018)
;; 1. √ Remove specific authorization model - replace by a query-level resolution step
Expand Down
241 changes: 2 additions & 239 deletions src/d2q/impl.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
[d2q.datatypes]
[d2q.impl.datatypes]

[taoensso.tufte :as tufte :refer (defnp p profiled profile)])
[#_taoensso.tufte d2q.impl.tufte-mock ;; NOTE comment one or the other to toggle profiling
:refer (p profiled profile)])
(:import (java.util List ArrayList)
(clojure.lang PersistentVector)
(d2q.datatypes ResultCell)
(java.io Writer)))

Expand Down Expand Up @@ -695,243 +695,6 @@

)

;; ------------------------------------------------------------------------------
;; Old API

(comment ;; FIXME DEPRECATED
(defn q-fcalls
[query]
(:d2q-query-fcalls query))

(defn fc-field-name [fc]
(:d2q-fcall-field fc))

(defn fc-key [fc]
(:d2q-fcall-key fc))

(defn fc-arg [fc]
(:d2q-fcall-arg fc))

(defn fc-subquery [fc]
(:d2q-fcall-subquery fc))

(defn table-resolver-for-field
[field]
(tp/field-table-resolver field)
)

(defn resolve-table
[tr qctx f+args o+is]
(try
(tp/resolve-table tr qctx f+args o+is)
(catch Throwable err
(mfd/error-deferred err))))

(defn field-by-name
[engine field-name]
(or
(tp/field-by-name engine field-name)
(throw (ex-info
(str "No Field registered under name " (pr-str field-name))
{:d2q.field/name field-name}))))

(defn scalar-typed?
[field]
(tp/field-scalar? field))

(defn ref-typed?
[field]
(not (scalar-typed? field)))

(defn many-typed?
[field]
(tp/field-many? field))

(defrecord EnrichedQClause
[key field-name args nested field table-resolver src-qc])

(defn enrich-qc [engine qc]
(let [field-n (fc-field-name qc)
f (field-by-name engine field-n)
tr (table-resolver-for-field f)]
(->EnrichedQClause
(fc-key qc)
field-n
(fc-arg qc)
(fc-subquery qc)
f
tr
qc)))

(defn merge-maps-arrs
"Given a seq of l-sized arrays of maps, returns an array of maps merged together."
#^"[Ljava.lang.Object;" [l map-arrays]
(let [map-arrs (to-array map-arrays)
ret-arr (object-array l)]
(impl.utils/doarr-indexed! [[i _] ret-arr]
(aset ret-arr i
(persistent!
(impl.utils/areduce-iv
[[m _ ^objects map-arr] map-arrs]
(transient {})
(->> (aget map-arr i)
(reduce-kv assoc! m)))
)))
ret-arr))

(comment
(vec
(merge-maps-arrs
3
(for [k [:a :b :c]]
(object-array (for [i (range 4)] {k i})))))
=> [{:a 0, :b 0, :c 0} {:a 1, :b 1, :c 1} {:a 2, :b 2, :c 2}]
)

(defn populate
"`objs` is an array of DD objects, returns an array of corresponding DD results (maps or nil)."
[engine, qctx, query, ^objects objs]
(mfd/future
(let [e-qs
(mapv #(enrich-qc engine %) (q-fcalls query))

o+is
(vec (impl.utils/amap-indexed [[i o] objs] [o i]))

p_transformed-entities
(-> (tp/transform-entities engine qctx query o+is)
(mfd/chain vec)
(mfd/catch
(fn [^Throwable err]
(throw (ex-info
(str "Error when transforming entities: " (pr-str (class err)) " : " (.getMessage err))
{:query query}
err)))))]
(-> p_transformed-entities
(mfd/chain
(fn [o+is]
(let [n-objs (alength objs)

by-tr (group-by :table-resolver e-qs)
p_table-batches
(->> by-tr
(map
(fn [[tr e-qs]]
(let [f+args (->> e-qs
(map (fn [e-qc]
[(:key e-qc) (:field-name e-qc) (:args e-qc)])))
p_results (-> (resolve-table tr qctx f+args o+is)
(mfd/catch
(fn [^Throwable err]
(throw (ex-info
(str "Tabular Resolver " (pr-str (tp/tr-name tr))
" failed with " (pr-str (class err)) " : " (.getMessage err))
(merge
{:d2q.resolver/name (tp/tr-name tr)
:f+args f+args}
(ex-data err))
err)))))
{ref-e-qs true scalar-e-qs false} (group-by #(ref-typed? (:field %)) e-qs)]
(mfd/chain p_results
(fn [results]
(let [k->scalar
(impl.utils/index-and-map-by
:key (constantly true)
scalar-e-qs)
k->ref
(impl.utils/index-and-map-by
:key
(fn [e-qc]
(let [;; The list of all children via e-qc
children-objs-list (ArrayList.)
many? (-> e-qc :field many-typed?)
;; an array of arrays, in the case of a to-many relationship, holding the ordered result maps of the children.
children-results-arrs (when many?
(object-array n-objs))]
[children-objs-list
many?
children-results-arrs
e-qc]))
ref-e-qs)

arr-scalars
(let [arr-scalars (object-array n-objs)]
(doseq [[parent-i k v] results]
(let [tm (or
(aget arr-scalars parent-i)
(transient {}))]
(aset arr-scalars parent-i
(if-let [_ (k->scalar k)]
(assoc! tm k v)
(if-let [[^List children-list, many?, ^objects children-results-arrs] (k->ref k)]
(do
(if many?
(do
(.addAll children-list
(into []
(map-indexed
(fn [j child]
[child parent-i j]))
v))
(aset children-results-arrs parent-i (object-array (count v))))
(.add children-list [v parent-i]))
tm)
(throw (ex-info
(str "Unidentified key " (pr-str k))
{:k k})))))))
(impl.utils/doarr-indexed! [[i tm] arr-scalars]
(when (some? tm)
(aset arr-scalars i (persistent! tm))))
arr-scalars)

p_ref-arrs
(->> k->ref
(mapv (fn [[k [^List children-list, many?, ^objects children-results-arrs, e-qc]]]
(let [children-objs (impl.utils/amap-indexed
[[_ [o _]]
(to-array children-list)]
o)
;; recursive call
p_populated (populate engine qctx (:nested e-qc) children-objs)]
(mfd/chain p_populated
(fn [^objects i+rs]
(if many?
(do
(impl.utils/doarr-indexed! [[i r] i+rs]
(let [[_ parent-i j] (.get children-list (int i))]
(-> children-results-arrs
^objects (aget parent-i)
(aset j r))))
(impl.utils/amap-indexed
[[_ a-children-maps]
children-results-arrs]
(when (some? a-children-maps)
{k (vec a-children-maps)})))
(let [arr (object-array n-objs)]
(impl.utils/doarr-indexed! [[i r] i+rs]
(let [[_ parent-i] (.get children-list (int i))]
(aset arr parent-i {k r})))
arr))))
))))]
(apply mfd/zip
(doto (mfd/deferred) (deliver arr-scalars))
p_ref-arrs)
)))
)))
(apply mfd/zip))]
(mfd/chain p_table-batches
(fn [arr-seqs]
(merge-maps-arrs n-objs (apply concat arr-seqs))))
)))))))

(defn query
[engine qctx normalized-query obj-root]
(mfd/chain (populate engine qctx normalized-query (to-array [obj-root]))
(fn [^objects i+rs]
(-> i+rs (aget 0) (or {})))))

)

;; ------------------------------------------------------------------------------
;; Custom printing

Expand Down
8 changes: 8 additions & 0 deletions src/d2q/impl/tufte_mock.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(ns d2q.impl.tufte-mock)

(defmacro p [& args] (last args))

(defmacro profile [& args] (last args))

(defmacro profiled [& args] (last args))

4 changes: 2 additions & 2 deletions test/d2q/test/example/persons.clj
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@

;; Some notes:
;; 1. It makes no sense for a scalar-typed Field to be called with a :d2q-fcall-subquery.
;; 2. For scalar-typed attribute, the notion of cardinality makes no sense:
;; a scalar-typed attribute may compute any type of values (including maps or vectors),
;; 2. For scalar-typed Field, the notion of cardinality makes no sense:
;; a scalar-typed Field may compute any type of values (including maps or vectors),
;; and the d2q engine won't care.


Expand Down

0 comments on commit cd62f27

Please sign in to comment.