This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-01
Channels
- # announcements (21)
- # architecture (6)
- # aws (18)
- # babashka (14)
- # beginners (231)
- # boot (1)
- # calva (2)
- # chlorine-clover (22)
- # cider (34)
- # clara (16)
- # clj-kondo (53)
- # cljdoc (5)
- # cljs-dev (22)
- # cljsrn (3)
- # clojure (283)
- # clojure-europe (24)
- # clojure-italy (9)
- # clojure-nl (5)
- # clojure-spec (5)
- # clojure-uk (57)
- # clojurescript (14)
- # core-typed (8)
- # cursive (4)
- # data-science (11)
- # datomic (41)
- # docker (24)
- # duct (2)
- # emacs (2)
- # exercism (29)
- # fulcro (96)
- # graalvm (4)
- # jobs-discuss (1)
- # kaocha (53)
- # lambdaisland (20)
- # malli (5)
- # nrepl (4)
- # observability (7)
- # off-topic (40)
- # pathom (44)
- # pedestal (8)
- # re-frame (19)
- # shadow-cljs (58)
- # spacemacs (2)
- # sql (9)
- # tools-deps (15)
- # vim (3)
- # yada (10)
Hello
pc/reader3
is trying to "inspect" my "entity" values, and it cause issues
(let [register [(pc/resolver
`foo
{::pc/input #{:db}
::pc/output [:b]}
(constantly {}))]
parser (p/parser {::p/plugins [(pc/connect-plugin {::pc/register register})]})
env {::p/reader [p/map-reader
pc/reader3
pc/open-ident-reader]}
conn (d/connect (doto (str "datomic:mem://" (d/squuid))
d/create-database))
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
`foo
{::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
pc/reader3
pc/open-ident-reader]}
conn (d/connect (doto (str "datomic:mem://" (d/squuid))
d/create-database))
db (d/db conn)]
(parser env `[{([:a "a"] {:pathom/context {:db ~db}})
[:b]}]))
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)
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
Object
(final-value? [this ] false)
nil
(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)
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 ,,,}
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
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)
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’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
[detail]
;; 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
[all-customers]
;; result will be [{:customer/id ?id ,,,} ,,,]
(map :customer/id all-customers))
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 queryAs #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
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
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
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]
[:customer/name
:customer/email
{:customer/last-purchase
[:product/id :product/name :product/price]}]}]
ostensibly there’s two identities here: :product/id
and :customer/id