Fork me on GitHub
#sql
<
2018-09-17
>
mark_d19:09:22

I’m new to clojure and I’m not familiar with all the asynchronous mechanisms so I’m looking for a little guidance. I have a jdbc query that could take minutes or hours. How do I construct an asynchronous query mechanism? Specifically, I want the function to return immediately and perhaps a callback function for processing the results after the query returns. Is there a function I could call which would take a query as the first argument, execute it on a thread and return and a callback function which will be called when the results of the query return. For example,

(do-async  (jdbc/query db-spec query) :callback (fn [response] (process-response response))))
I’ve been reading the docs for core.async but can’t seem to put it all together in a cohesive way. Any pointers to guides, examples, blog posts or libraries would be appreciated. Thanks!

hiredman19:09:50

you likely just want a thread

hiredman19:09:00

so use future

hiredman19:09:31

if you are coming from a js background, async there is usually synonymous with multiple threads of execution which are achieved by slicing things in to multiple tasks that executed one at a time on a single real thread

hiredman19:09:51

the jvm is a multithreaded runtime, so if you want multiple threads of execution, you can just have them

mark_d19:09:14

@hiredman Thanks for your help. I’ll read up on thread/future. I have a Java UI background so I’m thinking of a mechanism like SwingWorker

hiredman19:09:43

yeah, future

mark_d20:09:19

@hiredman I’ve been reading a bit about future and I’m not clear how I can process the results asynchronously. It appears that we must dereference the result (channel?) in order to get the query results and that dereference will block until the function passed into the future is complete. I just want to define a callback function which will be called with the query results when the future task completes. Is there any guidance on that use case?

hiredman20:09:50

you don't need a callback

hiredman20:09:30

(future (some-function (some-query-function)))

hiredman20:09:03

future returns a future (not a channel)

hiredman20:09:21

you don't need to deref a future

hiredman20:09:43

when you give it stuff to run, it is immediately run on another thread in a threadpool

hiredman20:09:12

deref returns the result if of whatever you ran in the future if you want it

mark_d20:09:46

I’m not getting the results I’m looking for. It appears that I’ll have to poll the future to determine when it is done and then I can dereference it to extract the value. How can I avoid polling and have the results passed to a function automatically when the future is done?

mark_d20:09:46

Sorry. Let me try your suggestion of putting the future on the “callback function”

tanzoniteblack20:09:54

On a note: JDBC is not asynchronous. The most you can do with it is execute on a different thread so you're original calling thread isn't blocked, which is what future does for you. If you want to run it on a separate thread, and then have a function process the result in the future without polling, you probably want to look into either core.async, manifold, or the simple method that @hiredman suggested of: (future (my-final-result-fn (my-long-running-query)))

tanzoniteblack20:09:12

I would avoid the two libraries I mentioned until you know you actually need something more complex than the future version

mark_d20:09:16

I just did a small experiment and I think the mechanism that @hiredman will work for me. Thank you all for your help and guidance