Fork me on GitHub
#pathom
<
2020-03-06
>
yenda14:03:31

So if someone ends up having the same idea what I did is using a raw subscription:

(defn subscribe
  [local-query]
  (re-frame/subscribe [::query local-query]))

(re-frame/reg-sub-raw
 ::query
 (fn [app-db [_ [query-subscription-key & args :as query-subscription]]]
   (let [query-fn (query-subscription-key->query-fn query-subscription-key)
         query [(apply query-fn args)]]
     (take! (eql.local-parser/parser {:app-db app-db} query)
            (fn [response]
              (re-frame/dispatch [::local-response query-subscription query response])))
     (reagent.ratom/make-reaction
      (fn [] (get-in @app-db [::queries query-subscription]))
      :on-dispose #(re-frame/dispatch [::query-unsubscribed query-subscription])))))
then I cleanup the response
(clojure.walk/prewalk
                          (fn [v]
                            (if (and (keyword? v) (= v ::p/not-found))
                              nil
                              v))
                          response)
if the cleaned-up response is the same as the response I don't do a remote query However I decided to give up on it because I realized it was pointless, I wouldn't even get proper updates of the subscription when doing a mutation that changes the data for instance. Since the app-db is already denormalized by being filled upon reception of a remote response, I decided to simply work locally with regular re-frame susbcription and skip the local parser completly. So it works like that: • I make remote queries as soon as I know I need the data (for instance when app loads, big ass query, when re-frame event navigating to a screen is dispatched, query the data that will be needed for that screen, etc...) • When I receive a response, I have a reduce-handler function that goes over each key of the response map and calls a defmulti handler that dispatches on the key, which in some keys is called recursively if results are nested. These handlers are doing what has to be done in the app based on the results, such as populated app-db in a normalized way but also sometime navigating or doing other effects • Components use re-frame subscriptions to get the data, it doesn't try to denormalize the data, so if a component needs a person, it susbcribes to [:person person-id], if a sub component needs the list of contacts, person has a vector of contact-ids, so to show a list of contacts component, it would be passed the vector of ids, and each element of the list would subscribe to [:person contact-id] That way I can keep app-db normalized, and I don't have to make local queries, when something changes in the db as a result of a mutation or new query, only the concerned components will update. Ofc there might be some inefficiencies, some data may be queried more often than necessary. I will look into it in the future as it is not a big problem for now, especially since the app-db is basically a cache and some data would need a cache invalidation strategy so until bandwith becomes an issue it's fine. A potential solution would be to add a key to entities I don't want to requery and check that before sending a remote query

yenda14:03:17

thanks for the tip! how would I know that the parser didn't find everything I want though? Anyway as I said I gave up on the local parser as I realized it was adding unnecessary complexity and it was adding some issues as well

yenda14:03:47

my main goal was to see if I could have a simple easy way to only query the missing data on the remote parser, but for that I am not sure having a local parser is the best strategy since re-frame susbcriptions are much simpler and faster to display data, and I could find something else on the remote query side