graphql

2021-12-08T04:19:38.088Z

Regarding superlifter, When used with Lacinia, it is useful to allow a field resolver to modify the application context, with the change exposed just to the fields nested below, but to any depth. (resolve/with-context result new-context) In our specific use-case, we’d like to update a specific db parameter for just to the field below. However superlifter requires the parameter to be placed in its context. We are able to specify the initial context via the :urania-opts key, but what’s the recommended way to update the urania env just to the fields nested below, but to any depth? Also posted in https://github.com/oliyh/superlifter/issues/26

2021-12-08T09:15:53.088500Z

We've just made our (datomic) db value a part of the identity of our fetch records

2021-12-08T10:40:38.089500Z

Yes, that’s our use case as well. Datomic transact function give us a db-after value after transaction, so we need to use that as a basis in all of the fields nested below.

2021-12-08T12:07:19.090300Z

We have a db value in the lacinia context, which we update at the end of a mutation by passing a new context to lacinia using resolve/with-context.

2021-12-08T12:17:49.090500Z

Yup, assuming there are multiple mutation transaction running concurrently, thus returning multiple db value, each with different T. How should the data-fetching function (running on a thread pool) know which db (= T) to use?

2021-12-08T12:35:16.091400Z

I think it's not possible to run multiple mutations in a single graphql document if you're using lacinia

2021-12-08T12:37:57.091600Z

Well…… I’m not so sure about that……

2021-12-08T12:43:55.091800Z

Let’s go back to the original question. How do you update superlifter’s context? Presumably you could transact, get a new db, somehow update superlifter’s context, and finally use resolve/with-context to change lacinia’s context.

2021-12-08T12:53:04.092100Z

> Well…… I’m not so sure about that…… I checked, My original statement is not true (any more?) according to [the docs](https://lacinia.readthedocs.io/en/latest/mutations.html). Either way; they're executed serially. > How do you update superlifter’s context I just checked our usage; and we use urania-opts to initially set a context using an interceptor. In our resolvers we use (with-superlifter context before resolving anything, where context is the first argument of our resolver. I think this is enough to get it to work. Most of our resolvers return stubs and require the superlifter so our approach would rely pretty heavily on this.

2021-12-08T13:04:45.092300Z

How do you pass a db to your data fetcher (i.e. superfetcher)? 1. via superlifter’s :urania-opts 2. via superfetcher’s identity (s/def-superfetcher FetchFoo [id db] ...) 3. via a shared atom And how do you change to a new db after a transaction?

1️⃣ 1
3️⃣ 1
2️⃣ 1
2021-12-08T13:44:51.093200Z

(same company as thumbnail) We don’t use the macro that superlifter offers; we just have simple defrecords implementing the DataSource protocol:

(defrecord MyFetcher [db id]
  u/DataSource
  (-identity [_] [(db->cache-key db) id])
  (-fetch [_ env] ...))

(defn my-fetcher [db id] 
  (->MyFetcher db id))

2021-12-08T13:46:03.093400Z

So; kinda like your option 2, but without the macro

2021-12-08T13:49:42.093800Z

IOW, to go back to your original question, we dont update the superlifter context; database values are not in the superlifter context for us

2021-12-08T13:50:04.094Z

We do update the lacinia context with a new db value, and we use that to create new fetchers (as show above)

👀 1
2021-12-08T13:51:27.094200Z

Meaning the selection below a mutation uses the db-after value of the datomic transaction

2021-12-08T13:52:08.094400Z

Does that help?

2021-12-08T14:57:10.094700Z

Got it. It makes so much sense now. We’ve started with similar pattern (using the macro), but somehow the query won’t get batched. Maybe there is something wrong with our implementation, but it works if you implements a BatchedSource, right?

2021-12-08T15:31:17.096800Z

😅 I forgot we ditched the superlifter macros, thanks @lennart.buit. Debugging the batching can be tricky. we implement both DataSource and BatchedSource indeed, maybe you can share some code?

👍 1
2021-12-08T15:32:37.097Z

Yeah my example only caches, no batching. You need to implement u/BatchedSource to do batching

👍 1
2021-12-08T16:08:24.097500Z

Got it. Thanks.

(s/def-superfetcher FetchSession [id context]
  (fn [coll _]
    (map clj->gql
         (identity/find-session-by-ids context (map core/to-eids coll)))))

(def fetch-session-by-id ->FetchSession)
context is a map that contains db. It should work though…. Maybe I should try implementing u/BatchedSource without the macro.

2021-12-08T23:09:01.097800Z

So whats important to know tho, the superlifter macro will use (:id this) as identity for your datasource. If you truly care about using the right database value for the right subquery, you need to incorporate the database value in your cache key.

2021-12-08T23:09:31.098Z

I strongly recommend trying the record / protocol, and work your way back

2021-12-09T00:00:59.098200Z

Got it, thanks!

2021-12-08T04:43:08.088300Z

Current idea: Use superlifter/add-bucket! to create a new bucket every time we need to context-switch, but there will be lots of buckets to sync.