funcool

A channel for discussing and asking questions about Funcool libraries https://github.com/funcool/
mitchelkuijpers 2015-08-18T10:07:34.000123Z

Cool a funcool channel! 😁

niwinz 2015-08-18T10:16:36.000124Z

\o/

2015-08-18T10:28:09.000125Z

o/

mitchelkuijpers 2015-08-18T10:28:17.000126Z

\o

mitchelkuijpers 2015-08-18T14:00:20.000127Z

Can I only return a manifold deferred as body in a response but not as a return value?

mitchelkuijpers 2015-08-18T14:00:37.000128Z

So I can do this https://funcool.github.io/catacumba/latest/#body-as-deferred-manifold

mitchelkuijpers 2015-08-18T14:01:46.000129Z

but not:

(d/chain (jira-api/get-user-groups host user-key)
             #(http/ok %))

mitchelkuijpers 2015-08-18T14:02:49.000130Z

(defn my-async-handler
  [context]
  (let [result (d/future (Thread/sleep 1000) "hello world")]
    (d/chain result
             #(http/ok & {"content-type" "text/plain"}))))

mitchelkuijpers 2015-08-18T14:02:58.000131Z

the second one is more obvious

mitchelkuijpers 2015-08-18T14:13:21.000132Z

I have a handler in my chain that checks some authorization and does a call with aleph and I would like that to be async

niwinz 2015-08-18T14:17:35.000133Z

Hmm

niwinz 2015-08-18T14:17:53.000134Z

Maybe some extend-protocol is missing for the manifold deferred

mitchelkuijpers 2015-08-18T14:18:07.000135Z

Yeah I checked the code that seems to be the issue

mitchelkuijpers 2015-08-18T14:18:20.000136Z

because catacumba says

mitchelkuijpers 2015-08-18T14:18:25.000137Z

2015-08-18 16:11:58,966 WARN  [r.s.i.NettyHandlerAdapter] No response sent for GET request to /api/1.0/companies (last handler: catacumba.impl.handlers$eval17761$fn$reify__17763)

niwinz 2015-08-18T14:18:35.000138Z

Because the return value is handled by one protocol and the body sending by other

niwinz 2015-08-18T14:19:28.000139Z

Efectivelly....

niwinz 2015-08-18T14:20:04.000140Z

the deferred imlementation is not found for IHandlerResponse protocol.

mitchelkuijpers 2015-08-18T14:20:43.000141Z

Yeah, I'll take a stab at it

mitchelkuijpers 2015-08-18T14:20:54.000142Z

Would you like a pull request for that?

niwinz 2015-08-18T14:22:00.000143Z

Yes and No xD

niwinz 2015-08-18T14:22:24.000144Z

Seems that the implementation of deffered for body handling not will work as you expect

mitchelkuijpers 2015-08-18T14:22:49.000145Z

Oh

niwinz 2015-08-18T14:23:30.000146Z

This is because the body handling is just the content

niwinz 2015-08-18T14:23:46.000147Z

but in your examples the deferred will be resolved in a response

niwinz 2015-08-18T14:23:54.000148Z

not the body content

niwinz 2015-08-18T14:24:21.000149Z

And I think that your use case is pretty common so this should be solved

mitchelkuijpers 2015-08-18T14:24:30.000150Z

True, I want to delegate or return a forbidden

niwinz 2015-08-18T14:25:12.000151Z

Give me some time for finish that I'm currently working on, and later I will try to fix this inconsistences

mitchelkuijpers 2015-08-18T14:25:28.000152Z

Thanks @niwinz much appreciated

mitchelkuijpers 2015-08-18T14:25:48.000153Z

Were deploying our app next week with catacumba!

niwinz 2015-08-18T14:27:06.000154Z

Oh great! Let me know anything

mitchelkuijpers 2015-08-18T14:29:05.000155Z

Sure will keep you posted, we are building an atlassian connect addon with it. It is in it's very early stage http://addons.avisi.com/relationsforjira/

mitchelkuijpers 2015-08-18T14:29:42.000156Z

Having a lot of fun with catacumba it's pedestal with docs

niwinz 2015-08-18T14:30:50.000157Z

I'm very glad to hear about this!

niwinz 2015-08-18T14:31:14.000158Z

One thing... the way to attach a watcher

niwinz 2015-08-18T14:31:32.000159Z

to deferred is using the (d/on-realized...), no?

mitchelkuijpers 2015-08-18T14:33:24.000160Z

yes I think so let me double check it for you

mitchelkuijpers 2015-08-18T14:33:49.000161Z

(d/on-realized d
    (fn [x] (println "success!" x))
    (fn [x] (println "error!" x)))

niwinz 2015-08-18T14:34:21.000162Z

Ok, nice! I will modify almost all implementation of IResponseHandler for async value for make it consistent

niwinz 2015-08-18T14:34:32.000163Z

async values returned as is, should return a proper response

niwinz 2015-08-18T14:34:42.000164Z

and async value in body should return the body value

mitchelkuijpers 2015-08-18T14:34:45.000165Z

Yeah nice

mitchelkuijpers 2015-08-18T14:35:02.000166Z

Then you can basically make a non blocking chain of handlers ^^

niwinz 2015-08-18T14:35:14.000167Z

Yes!

niwinz 2015-08-18T14:54:55.000168Z

I have it almost done

niwinz 2015-08-18T14:55:03.000169Z

I will publish the snapshot release

niwinz 2015-08-18T14:57:36.000170Z

The 0.6.0-SNAPSHOT is published with that inconsistences fixed and with more tests for that use cases

niwinz 2015-08-18T14:57:42.000171Z

@mitchelkuijpers: ^

niwinz 2015-08-18T14:57:57.000172Z

Please check if it works for you.

mitchelkuijpers 2015-08-18T14:58:05.000174Z

Yes thnx @niwinz

mitchelkuijpers 2015-08-18T14:59:07.000175Z

Ill trying it out as we speak

mitchelkuijpers 2015-08-18T15:01:43.000176Z

restarting the repl....

mitchelkuijpers 2015-08-18T15:02:40.000177Z

Ouch

mitchelkuijpers 2015-08-18T15:02:43.000178Z

`

mitchelkuijpers 2015-08-18T15:02:47.000179Z

ratpack.exec.UnmanagedThreadException: Operation attempted on non Ratpack managed thread 'aleph-pool-1-2'

niwinz 2015-08-18T15:03:05.000180Z

very strange...

niwinz 2015-08-18T15:03:43.000181Z

this can happens when you are writting directly to the ratpack from some other thread

mitchelkuijpers 2015-08-18T15:04:17.000183Z

Aha I do a call with aleph to a webservice and then process the result

mitchelkuijpers 2015-08-18T15:04:34.000184Z

so I should put this in another or a new deferred

mitchelkuijpers 2015-08-18T15:04:38.000185Z

or a promise or whatever

niwinz 2015-08-18T15:04:47.000186Z

hmm no, it just ok, it should work

niwinz 2015-08-18T15:05:25.000189Z

let see this test case. It just execute something in an other thread..

niwinz 2015-08-18T15:07:01.000191Z

The exception is not related to the response handling

niwinz 2015-08-18T15:07:06.000192Z

i think

mitchelkuijpers 2015-08-18T15:07:47.000193Z

Hmm very weird

niwinz 2015-08-18T15:08:01.000194Z

I'm trying understand it...

mitchelkuijpers 2015-08-18T15:08:53.000195Z

at ratpack.exec.internal.ThreadBinding$$Lambda$99/1786206212.get(Unknown Source)

niwinz 2015-08-18T15:08:55.000196Z

Can you give me handler code? a little simplfied previw of it...

niwinz 2015-08-18T15:09:13.000197Z

I want understand why it is happens

mitchelkuijpers 2015-08-18T15:09:19.000198Z

Hmm I'll see if I can create a very small example

mitchelkuijpers 2015-08-18T15:13:04.000199Z

(defn example
  [context]
  (d/chain
   (http/get "<http://www.google.nl>")
   :body
   #(cthttp/ok % {:Content-Type "plain/text"})))

mitchelkuijpers 2015-08-18T15:14:36.000200Z

[manifold.deferred :as d]
            [aleph.http :as http]
            [catacumba.http :as cthttp]

mitchelkuijpers 2015-08-18T15:14:46.000201Z

Also gives

ratpack.exec.UnmanagedThreadException

mitchelkuijpers 2015-08-18T15:16:29.000204Z

yess threadlocals the root of all evil

niwinz 2015-08-18T15:17:35.000205Z

I know, but ratpack tries to use them for control from that threads the response is written

niwinz 2015-08-18T15:18:16.000206Z

I'll try to reproduce the error with your code

niwinz 2015-08-18T15:18:21.000207Z

and try to fix it..

mitchelkuijpers 2015-08-18T15:19:06.000208Z

I could also

mitchelkuijpers 2015-08-18T15:19:39.000209Z

If it's only a aleph error I could also switch to another http lib

mitchelkuijpers 2015-08-18T15:19:51.000210Z

But aleph is the only async lib I know of

niwinz 2015-08-18T15:21:55.000211Z

I don't want condition your code because catacumba does not handles well this situation.

niwinz 2015-08-18T15:22:52.000212Z

It is just work in test cases

niwinz 2015-08-18T15:22:59.000213Z

I'm clearly don't understand xD

mitchelkuijpers 2015-08-18T15:23:25.000214Z

Yeah me neither

mitchelkuijpers 2015-08-18T15:23:38.000215Z

If I think of something I'll let you know

niwinz 2015-08-18T15:23:58.000216Z

Your example as is is just works in tests

mitchelkuijpers 2015-08-18T15:24:03.000217Z

Really?

niwinz 2015-08-18T15:24:08.000218Z

Yes...

mitchelkuijpers 2015-08-18T15:24:51.000219Z

Ow lol forgot todo (reset) ...

mitchelkuijpers 2015-08-18T15:24:57.000220Z

😱

niwinz 2015-08-18T15:25:02.000221Z

I suspect that in some previous steps to that handler something goes out of the ratpack managed threads

niwinz 2015-08-18T15:25:27.000222Z

what?

mitchelkuijpers 2015-08-18T15:26:08.000223Z

I call this function:

mitchelkuijpers 2015-08-18T15:26:11.000224Z

(defn get-user-groups
  [host user-key]
  (-&gt; (get host "/rest/api/2/user" {:query-params {:key user-key
                                                   :expand "groups"}})
      (d/chain (fn [{:keys [body]}]
                 (let [groups (-&gt; body
                                  bs/to-string
                                  (json/decode true)
                                  :groups
                                  :items)]
                   (mapv :name groups))))
      (d/catch (fn [e]
                 (log/error e "Error occured while retrieving user" user-key)
                 []))))

mitchelkuijpers 2015-08-18T15:26:29.000225Z

and then do a chain in the handler on this result

niwinz 2015-08-18T15:27:15.000226Z

The exception happens before

mitchelkuijpers 2015-08-18T15:27:22.000227Z

so something along the lines of: ` (d/chain (get-user-groups ...) (if (foo) (forbidden) (delegate)))

niwinz 2015-08-18T15:27:40.000228Z

the exception now happens before your code as I can observe in the stack trace

niwinz 2015-08-18T15:29:18.000231Z

As you can observe this is a problematic line and is executed before the handler code

niwinz 2015-08-18T15:29:40.000232Z

it is nothing related to the handler code instead to something that runs after

niwinz 2015-08-18T15:29:46.000233Z

how you start the

niwinz 2015-08-18T15:30:07.000234Z

server or do you have any other chain that wraps something in aleph context...

niwinz 2015-08-18T15:30:09.000235Z

?

mitchelkuijpers 2015-08-18T15:30:26.000236Z

(let [conn (database/context-&gt;connection context)
        host (:host context)
        permitted-groups (set (mapv :permissions/group-name
                                    (database/get-permissions conn host)))
        user-key (:userKey (:user context))
        user-groups (jira-api/get-user-groups host user-key)]
    (d/chain user-groups
             set
             (fn [_] (ct/delegate context)))))

niwinz 2015-08-18T15:30:43.000237Z

ohh yess

niwinz 2015-08-18T15:30:47.000238Z

here is the problem

niwinz 2015-08-18T15:31:15.000239Z

I think

niwinz 2015-08-18T15:31:29.000240Z

you are calling the delegate,.. from the aleph context

niwinz 2015-08-18T15:31:43.000241Z

Now, I'll try to reproduce the error knowing that

mitchelkuijpers 2015-08-18T15:31:49.000242Z

Aha and then I am int he wrong thread

mitchelkuijpers 2015-08-18T15:31:56.000243Z

That makes alot of sense

niwinz 2015-08-18T15:34:47.000244Z

Yes, now I can reproduce it...

niwinz 2015-08-18T15:36:11.000245Z

But I'm currently don't know how I call the delegate in the proper way

niwinz 2015-08-18T15:36:15.000246Z

it need some research

niwinz 2015-08-18T15:44:33.000247Z

I have an idea on how to fix it bu at this time I shoud go out 😞

niwinz 2015-08-18T15:44:51.000248Z

I'll fix it later (in some hours 1 or 2)

niwinz 2015-08-18T15:45:44.000249Z

As a temporal workaround, use blocking operation and then call the delegate

niwinz 2015-08-18T15:45:50.000250Z

and when this issue is fixed

niwinz 2015-08-18T15:46:09.000251Z

you can return to the fully asynchronous way

mitchelkuijpers 2015-08-18T15:55:44.000252Z

@niwinz: That's what I am currently doing already :simple_smile:

mitchelkuijpers 2015-08-18T15:55:53.000253Z

Thanks for all your help dude

niwinz 2015-08-18T19:46:52.000254Z

@mitchelkuijpers: I just uploaded an other version to clojars (under 0.6.0-SNAPSHOT) that should allow the fully async delegation process

niwinz 2015-08-18T19:47:29.000255Z

the only restriction is that the return value of (ct/delegate ctx) should be the response (synchronous or asynchronous) of the handler.

niwinz 2015-08-18T19:48:52.000256Z

As I can see on your last code pasted here in channel, this is just how you are using. You are just return a deferred with the value of the execution of (ct/delegate...) so this code now should works as expected in fully asynchonous way.

niwinz 2015-08-18T19:50:11.000257Z

The curren implementation removes some speed improvements introduced previously but is just for fix this issue. I think that for the next version I will have time for fix it definitivelly with proper optimizations.

mitchelkuijpers 2015-08-18T19:51:27.000258Z

You Rock @niwinz will try it out tomorrow. Will also check out your code which fixes this, I am curious how you did it 👍

niwinz 2015-08-18T19:53:47.000259Z

\o/ Let me know any result! Now I go to sleep

niwinz 2015-08-18T20:59:17.000260Z

Take care that (ct/delegate...) function call signature is changed. It's no longer accepts context as first parameter. Now the ct/delegate is just a special response instead of special case.

niwinz 2015-08-18T20:59:38.000261Z

Read the changelog for an other, maybe more detailed explanation.

niwinz 2015-08-18T20:59:54.000262Z

I will update the doc for the next version about this breaking change.

niwinz 2015-08-18T21:00:39.000263Z

This change simplifies a lot how the context delegation works, because now is just an other response (that can be returned in sync or asynchronous way)

niwinz 2015-08-18T21:01:20.000264Z

And now. Definitively I go to sleep!

niwinz 2015-08-18T21:01:22.000265Z

\o/