From cd62f270f594d3ab22ab2f0586c3ab67f180066f Mon Sep 17 00:00:00 2001 From: Valentin Waeselynck Date: Fri, 12 Oct 2018 11:04:48 +0200 Subject: [PATCH] got rid of Tufte dep + various improvements --- deps.edn | 2 +- src/d2q/api.clj | 7 +- src/d2q/impl.clj | 241 +----------------------------- src/d2q/impl/tufte_mock.clj | 8 + test/d2q/test/example/persons.clj | 4 +- 5 files changed, 15 insertions(+), 247 deletions(-) create mode 100644 src/d2q/impl/tufte_mock.clj diff --git a/deps.edn b/deps.edn index e82cb23..751a991 100644 --- a/deps.edn +++ b/deps.edn @@ -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 diff --git a/src/d2q/api.clj b/src/d2q/api.clj index 756254a..eb3587d 100644 --- a/src/d2q/api.clj +++ b/src/d2q/api.clj @@ -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 diff --git a/src/d2q/impl.clj b/src/d2q/impl.clj index 3fc96be..5f0e88d 100644 --- a/src/d2q/impl.clj +++ b/src/d2q/impl.clj @@ -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))) @@ -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 diff --git a/src/d2q/impl/tufte_mock.clj b/src/d2q/impl/tufte_mock.clj new file mode 100644 index 0000000..80ecec6 --- /dev/null +++ b/src/d2q/impl/tufte_mock.clj @@ -0,0 +1,8 @@ +(ns d2q.impl.tufte-mock) + +(defmacro p [& args] (last args)) + +(defmacro profile [& args] (last args)) + +(defmacro profiled [& args] (last args)) + diff --git a/test/d2q/test/example/persons.clj b/test/d2q/test/example/persons.clj index c96eeb9..b911ff5 100644 --- a/test/d2q/test/example/persons.clj +++ b/test/d2q/test/example/persons.clj @@ -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.