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.
