hello everybody, I want to share with you some findings I just did. I'm working on the async support for Pathom 3, and this time I decided to compare two different implementations, one based in core.async and one based in promesa. I made the two implementations, and ran some benchmarks, here are the results: https://gist.github.com/wilkerlucio/a1cda78802c8a5f9cab92cb7c52fa69b
when I tried the core.async implementation I was a bit sad with the performance results, but than seeing those with Promesa made me really excited! the overhead using Promesa is quite close to the serial processing, which is a lot faster than every version of Pathom before that! and I would love to hear if have any opinions about this direction 🙏
Impressive! Can it be made pluggable?
This ^
I did some play here, and I checked its possible to also implement a promesa protocol to make other async things fulfill it, here is an example using core.async via said extension:
(extend-type cljs.core.async.impl.channels/ManyToManyChannel
promesa.protocols/IPromiseFactory
(-promise [this]
(p/create
(fn [resolve reject]
(go
(let [v (<! this)]
(if (error? v)
(reject v)
(resolve v))))))))
(comment
(let [start (system-time)]
(-> (p.a.eql/process (pci/register
(pco/resolver 'foo {::pco/output [:foo-async]}
(fn [_ _] (go {:foo-async "the-value"}))))
[:foo-async])
(p/handle (fn [result error]
(println "RES" result error))))))
I probably wont provide this in the library to avoid having the dep on core.async at all, but it can be a separated library, or a documentation page with the snippet
what you think?
Good approach. I really like core.async myself but having completablefutures is a good default, especially on the jvm. And it's easy to plug one into the others (you can make completablefuture impl for core. async readport/writeport that follows promise-chan impl, then overhead is really low I guess)
I wouldn't bake in interceptor usage tho, this is more opinionated, there's no standard and there are multiple good impl. in clojure with subtle differences.
I think that’s a great solution! like you said it could be a separate library if there’s enough demand for it but it’s also a pretty small change that just mentioning it in the README should be enough
you can convert anything to a promise-like from promise, as long as you have some way to trigger the callbacks (for resolving or rejecting), so you could wrap a channel to make it do it. is this what you were asking about?
I like promesa too. I think it is really close to bare CompletableFuture overhead
Is it possible to provide channel coercion in pathom3?
then you could possibly get the best of both worlds
compatibility with core.async and performance of promesa
it would be great if there could be one spot that we could do the channel -> promise conversion so that we could have our resolvers just return channels if we wanted
it might also be worth looking at kitchen-async(https://github.com/mhuebert/kitchen-async)
and then we can appropriately handle promise rejections in one spot as well since traditionally core async channels don’t really have a notion of “rejecting”
Something similar to how sieppari
works would be awesome where by default it only supports promesa
but you can bring in another namespace to extend what async libraries are supported (https://github.com/metosin/sieppari#external-async-libraries)