Indeed, if you call send(), pull a pipelined capability off of it, and then
drop the Promise that `send()` returned... then the logic to detect
disconnect will never run, because it's chained on the promise that you
canceled.

This does seem like a bug... I think I even remember hitting this before.
One way to work around it is to make sure you save the promise returned by
`send()` off to the side rather than throwing it away, so that it's allowed
to complete the disconnect-detection logic.

It's a bit hard for `ReconnectHook` to do this automatically, because if it
did, then you wouldn't actually be able to cancel calls made through
ReconnectHook... attempts to cancel would be ignored. I guess what you
really want is that the call won't be canceled if a pipelined capability
still exists. I think it would be possible to build that but it might be a
little convoluted...

-Kenton

On Mon, Sep 26, 2022 at 7:31 AM Vaci <[email protected]> wrote:

> I'm trying to add reconnection behaviour to capabilities with
> autoReconnect, but the behaviour isn't what I'd expect when I have multiple
> levels of reconnecting capabilities that are pipelined:
>
> Given a trivial schema that obtains one capability from another:
>
> reconnect-test.capnp:
> @0xa0fdcabdd0230110;
> interface TestB {
>   getA @0 () -> (a : Capability);
> }
>
> This example code deliberately creates capability B as disconnected, so
> I'd expect an attempt to reconnect the B capability, but instead, only
> reconnection of the A capability is attempted:
>
> reconnect-test.cpp:
> #include "reconnect-test.capnp.h"
> #include <capnp/reconnect.h>
> #include <kj/main.h>
> #include <kj/async.h>
> #include <kj/debug.h>
>
> int main(int argc, char* argv[]) {
>   kj::EventLoop loop;
>   kj::WaitScope waitScope{loop};
>
>   auto b = capnp::autoReconnect([&](){
>     KJ_LOG(WARNING, "Reconnecting B");
>     return TestB::Client{KJ_EXCEPTION(DISCONNECTED)};
>   });
>
>   auto a = capnp::autoReconnect([&]{
>     KJ_LOG(WARNING, "Reconnecting A");
>     return b.getARequest().send().getA();
>   });
>
>   try {
>     a.typelessRequest(0, 0, nullptr).send().wait(waitScope);
>   }
>   catch (kj::Exception& exc) {
>     KJ_LOG(ERROR, "1", exc);
>   }
>
>   try {
>     a.typelessRequest(0, 0, nullptr).send().wait(waitScope);
>   }
>   catch (kj::Exception& exc) {
>     KJ_LOG(ERROR, "2", exc);
>   }
> }
>
> Output:
> reconnect-test.cpp:12: warning: Reconnecting B
> reconnect-test.cpp:17: warning: Reconnecting A
> reconnect-test.cpp:17: warning: Reconnecting A
> reconnect-test.cpp:25: error: 1; exc = reconnect-test.cpp:13: disconnected
> reconnect-test.cpp:17: warning: Reconnecting A
> reconnect-test.cpp:32: error: 2; exc = reconnect-test.cpp:13: disconnected
>
> I'd expect the second attempt to result in a reconnection of the broken
> capability B when the (eventual) call to getARequest() occurs?
>
> If I remove the pipelining, and force the call to getARequest to complete,
> then B reconnects just fine.
>
> Vaci
>
> --
> You received this message because you are subscribed to the Google Groups
> "Cap'n Proto" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/capnproto/19ef7ff7-d419-4208-ab3d-4765a1fc99efn%40googlegroups.com
> <https://groups.google.com/d/msgid/capnproto/19ef7ff7-d419-4208-ab3d-4765a1fc99efn%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CAJouXQ%3D%3DK3heCZLrD-_STJ%2BdMzjH44TZnF5FZ-xinzzFdTO3xw%40mail.gmail.com.

Reply via email to