Fork me on GitHub

I'm having trouble getting Pathom(3) to make use of batch resolvers. I seem to be fulfilling the criteria for batch resolvers to kick in (maps are returned, or rather, a vector of maps), but Pathom seems to split them into individual calls anyway. I'm not sure what to look for while investigating this issue, what should I be looking out for?


can you share some code? we use batch resolvers on pathom3 and havent’ had such problem.


hello Henrik, looking at the graph it seems to be using batch correctly, that blue bar is kind of a “shared time” in the batch of the items


have you tried logging to see if there are many calls to the resolver?


maybe the reading is a bit confusing, but see that those blue bars are in "parallel", altough there is no parallel runner yet, the intention was to make an indication they are a single thing (the batch run), do you have an idea how we could make this clear?


Aha! That's interesting. I've also written a plugin to wrap each resolver call with a log to Honeycomb, where it looks like it's registering numerous calls to the same resolver:


Now I'm thinking that I might not be measuring what I think I'm measuring. When wrapping around ::pcr/wrap-resolve, am I wrapping around the call to the resolver, or the construction of the resolver, or something else?


(Btw, Honeycomb might be an example of a UX that is quite good at communicating where spans are children vs. siblings)


(defn wrap-resolver-with-honeycomb [resolve]
  (fn [env node]
    (wrap-honeycomb env (str (::pco/op-name node))
      (resolve env node))))


So, It's pretty clear to me that I've misunderstood wrap-resolve, and that this is the source of my confusion. Is there a way to wrap the invocation of a resolver, at the moment where it receives the inputs?


this expectation is correct, but as you are seeing, in the case of batch it get some caveats


indeed it always runs when the resolver gets the input, but, in the case of batch, it doesn't run immediatly


you can check if that happen, by looking at the output of what you are wrapping, in case of batch it will be a map with the key ::pcr/batch-hold on it, if you see that, this means the resolver isn't running now, and will run later as a batch


for observability purposes, you may want to ignore those cases


honeycomb looks nice 🙂


> for observability purposes, you may want to ignore those cases Right, but I also need some way of running it when the batch resolver finally runs. Is this possible? > honeycomb looks nice It is! Highly recommended.


Oh dear, and the result is a map with ::pcr/batch-hold on it. By then it is far too late to decide not to run Honeycomb. Honeycomb must be running while the resolver is evaluating… Do you see? It can't wait until after the resolver has run to evaluate the performance. In that case I'd have to run each resolver twice: first once, to detect whether it is a batch, then again to actually measure it.


I need either a way to determine ahead of time that it is a batch resolver, AND a way to run a plugin when the batch is actually executed, or (and this would be the vastly preferred case) I need an extension point that works the same way for batching and non-batching resolvers: i.e., it that runs on the actual execution of the resolvers, regardless of kind, and not on any preparatory step.


The first case would make it work, but it would also required two separate plugins to handle the one use case. The second case would make it work, and only require the one extension point.


good to hear about this case

👍 2

I've been giving second thoughs around the plugins, because batching also suffers from the limitations of the "wrapping pattern"


its also interesting to think about what is a good way to provide hooks for metrics like this


because measuring single vs batch, its not the same thing, and maybe is better to have distint ways to track it


That’s a good point, and it’s not the end of the world if it's two separate hooks. To me, it doesn't matter for the purposes of Honeycomb, since it's interesting enough to see where the app is spending a lot of time. From that point of view, it doesn't matter whether it’s batched or not. But I get that there may be other circumstances where it does matter.


With Honeycomb, I could inject the variable of whether it's batched or not, if this distinction could be known inside the plugin definition. This would enable me to split the analysis on those that are batched and not in the Honeycomb UI. Exposing an indicator of whether the plug-in is currently running inside a batch resolver or not might be more convenient than using two distinct integration points. That would leave it up to the creator of the plug-in to decide whether this information matters to them or not.


currently you can check if you look at the resolver, the "node" has ::pco/op-name, which you can use to lookup at ::pci/index-resolvers, them pull the config map with pco/operation-config

👍 2

the major missing point is a hook to know about the batch run time


that's currenty not available, but I can add that, just like to think a bit more about the whole plugin thing, this is something I can get to this week


@U06B8J0AJ yesterday I made some changes to what wrap-resolve wraps, before it was wrapping some higher process, but now it really wraps the resolve call (as I believe you expected, which makes sense), note now you get env input instead of env node, please let me know how that fits in your game

🎉 2

important to note though, now in the case of batch, you will only get 1 call to wrap-resolve with the batch (`input` will be a collection)


This works very well, thank you. I can now add the size of the input to the logging with Honeycomb. (i.e., "it took 59ms, but on the other hand there were 2291 inputs")