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.