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 <v...@vaci.org> 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 capnproto+unsubscr...@googlegroups.com.
> 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 capnproto+unsubscr...@googlegroups.com.
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