Fork me on GitHub

Hello pc/reader3 is trying to "inspect" my "entity" values, and it cause issues

(let [register [(pc/resolver
                  {::pc/input  #{:db}
                   ::pc/output [:b]}
                  (constantly {}))]
      parser (p/parser {::p/plugins [(pc/connect-plugin {::pc/register register})]})
      env {::p/reader [p/map-reader
      conn (d/connect (doto (str "datomic:mem://" (d/squuid))
      db (d/db conn)]
  (parser env `[(:b {:pathom/context {:db ~db}})]))
reader3 will throw because "walks" into db and try to get :children from datomic....Datum reader2 work fine


:pathom/context is only supported in ident joins


also occur in ident join I removed the ident join when i'm "trim down" to the "root problem"


(let [register [(pc/resolver
                  {::pc/input  #{:db :a}
                   ::pc/output [:b]}
                  (constantly {}))]
      parser (p/parser {::p/plugins [(pc/connect-plugin {::pc/register register})]})
      env {::p/reader [p/map-reader
      conn (d/connect (doto (str "datomic:mem://" (d/squuid))
      db (d/db conn)]
  (parser env `[{([:a "a"] {:pathom/context {:db ~db}})


sorry man, I don’t have the time to dig into this now (just looking in this example I don’t have any ideas on what is wrong), too many things happening right now, if you think that’s a bug please make a full example and open an issue on pathom or pathom-datomic (wherever you find its more relevant)


but it should work, right?


well, I don’t see you using the datomic plugin, I dont understand what p/reader3 trying to inspect means, so I have no idea whats going on in this


My problem: (map? db) return true with datomic db so functions like p/lift-placeholders that use clojure.walk, walk in datomic db, that can be problematic for performance but in my case, it's problematic because it thows when try to "walk" into Datum for examepl After fix lift-placeholders I found out that p/map->shape-descriptor has the same problem (not by clojure.walk, but by trying to use datomic db as map? ) I have 2 proposals: A: Create a IFinalValue protocol

(defprotocol IValue
  (final-value? [this]))
(extend-protocol IValue
  (final-value? [this ] false)
  (final-value? [this ] false))
So the user can extend it to datomic db for exemple to prevent this problem B: Create a ::p/final-value? optinal key inside env that defaults to (constantly false)


I’m trying to map out how a pathom/eql client would cache results of queries


it seems like there are two ways to assert whether some data is about the same entity based on a result: • an ident is directly queried for e.g. [{[:customer/id 123] [:customer/name :customer/email]}] the result of which would look like {[:customer/id 123] {:customer/name "Foo" :customer/email "bar"}} • a query results in a record(s) that contain some field that identifies the entity, e.g. the query [::latest-product] that results in {:product/id 1 ,,,}


any others people can think of?


the client caching problem seems a little hard to start due to the fact that there’s no explicit schema. I need some way of detecting whether something is an ident/identifying field, or have the user specify out of band. also the fact that it’s ambiguous whether a result will be a collection or scalar makes it harder to wrap my head around right now


hmm yeah, in GraphQL the result typically has some metadata: a __typename field that denotes whether a part of a result is a queryable object. if it’s not there, then you can reason that the part of the result you’re looking at is just some random JSON, not a part of the graph


apollo uses the typename and (by default) the id field to construct a cache key


yeah actually I have no idea how to tell if a part of a result is a queryable thing or just some random EDN.


@lilactown yeah, in fulcro the idents take care of this problem, because of the open nature of Pathom you need to add something like that to compare identities


because in pathom you may have multiple identities for the same thing, and also, different identities can partially share some values, but not others


I’m still trying to grok how idents work in fulcro (and how it’s different than idents in EQL and Pathom)

Björn Ebbinghaus16:04:24

It isn‘t different than eql and pathom.


it seems like a system would usually have a relatively global notion of identity. e.g. customer-ident and product-ident would be used throughout the app, right?


fulcro seems to couple identity to a component, which seems weird, but I am probably missing something


@lilactown fulcro integrates that because of automatic normalization, having that in the component allows fulcro to transform a response tree into a normalized database


so when new data enters the system, we can use a combination of component ident + props (ident is really just a fn applied to props) to decide where in the DB this data will go


so components with the same identity end up sharing data in the same place on the db (they get merged there), makes sense?


I think so 😅


I’d like to be able to have a library that works like:

(def all-customers-query
  [{:customers/all [:customer/id :customer/name :customer/email]}])

;; using helix for React components
(defnc customer-list
  ;; read from the cache all of the customers, maybe go fetch them
  (let [customers (use-query all-customers-query)]
and then elsewhere:
(def customer-detail-query
  '[{[:customer/id ?id] [:customer/name :customer/age :customer/email :customer/phone ,,,]})

(defnc customer-detail
  [{:keys [customer/id]}]
  ;; read from the cache this specific customer, maybe go fetch it
  (let [customers (use-query customer-detail-query {:id id})]
and it sounds like in order for these two components to maintain data consistency, I need to also add an additional mechanism that takes the result and computes an ident for each of the queries. something like
(def customer-detail-query
  '[{[:customer/id ?id] [:customer/name :customer/age :customer/email :customer/phone ,,,]}))

(defn customer-detail->ident
  ;; result will be {[:customer/id ?id] ,,,}
  (first (keys detail)))

(def all-customers-query
  [{:customers/all [:customer/id :customer/name :customer/email]}])

(defn all-customers->idents
  ;; result will be [{:customer/id ?id ,,,} ,,,]
  (map :customer/id all-customers))


sorry for the wall of text.


which I guess makes sense… but seems tedious


I don't think that this ?id template thing is a good path to solution The point of sale of EQL is that it's clojure data, so you don't need "query parameters" or "templates", you can just "assoc/concat" things

(def customer-detail-query
  [:customer/name :customer/age :customer/email :customer/phone])
(defnc customer-detail
       [{:keys [customer/id]}]
       ;; read from the cache this specific customer, maybe go fetch it
       (let [customers (use-query [:customer/id id] customer-detail-query)]))
Then use-query wil build/compose the final query


fair, it’s all just ideation


As #fulcro, you can add metadata in queries

(def product-query
  ^{:ident :product/id} [:product/id,,,])
(def customer-query
  ^{:ident :customer/id} [:customer/id,,,
                          {:customer/products product-query}])


But I think other solutions also may be possible: - server response with normalization metadata - global "index key" registry - Every map should contain a :index-by :costumer/id key


oops, reponses in wrong thread. but ok.


haha 🙂 I appreciate the responses!


in fulcro case, you declare with with render so

(defsc Foo [this prop]
  {:query [:foo/id :foo/name]
  :ident :foo/id}
  (div "Ok"))
(defsc Bar [this prop]
  {:query [:bar/id {:bar/foo (get-query Foo)}]
  :ident :bar/id}
  (div "Ok"))
All query/metadata is handled my defsc and get-query


how does fulcro handle multiple idents in a single query?


or is that even a thing


You can normalize the same data (users for example) both with user/id and user/email, for example I think that it's a anti-pattern. Not sure. This decision is on the component


hahahaha fair 😂


"just functions"


that sort of dovetails into something I’ve been wondering about: how does fulcro handle a query with multiple idents? e.g. I need the customer and the product they most recently bought:

[{[:customer/id 123]
    [:product/id :product/name :product/price]}]}]
ostensibly there’s two identities here: :product/id and :customer/id