Hi all,

I've been having fun playing around with Cap'n Proto and attempting to 
create simple subscriber/publisher classes using Cap'n Proto RPC and KJ.

I've created simple server/client pub/sub applications that use 
TwoPartyServer and TwoPartyClient classes. I've attempted to wrap the 
server app I made into it's own class using the constructor to setup the 
connection/listening logic. My current method has been to copy the 
implementation of the TwoPartyServer code and modify where needed.

The issue I'm facing is keeping the `listen()` promise alive to accept new 
incoming connections whilst I continue to do other work in the rest of the 
application.

Code for my normal working application:
```
kj::UnixEventPort::captureSignal(SIGINT);
auto io_context = kj::setupAsyncIo();
auto addrPromise = 
io_context.provider->getNetwork().parseAddress("unix:/tmp/capnp-server-example");
auto addr = addrPromise.wait(io_context.waitScope);
auto addrListen = addr->listen();
capnp::TwoPartyServer server(kj::heap<PublisherImpl<capnp::Text>>(sub_map));
auto server_listen = server.listen(*addrListen);
auto& timer = io_context.provider->getTimer();
auto pub = publishLoop(timer, 1);
io_context.unixEventPort.onSignal(SIGINT).wait(io_context.waitScope);
std::cout << "Shutting down Publisher\n";
```

Code for my wrapped class application constructor (the rest of the class is 
effectively the TwoPartyServer code):
```
template <typename T>
Publisher<T>::Publisher(const std::string& connection_address, 
kj::AsyncIoContext& io_context)
: tasks_(*this), connection_address_(connection_address), 
io_context_(io_context) {
auto listener = 
io_context_.provider->getNetwork().parseAddress(connection_address);
auto addr = listener.wait(io_context.waitScope);
auto addrListen = addr->listen();
addTask(listen(*addrListen));
}
```

This builds fine but I get an exception when I run the server.
```
error: exception = kj/async.c++:2714: failed: PromiseFulfiller was 
destroyed without fulfilling the promise.
```

I'm assuming the normal main application works because the `listen()` 
promise remains in scope but when I attempt to add the `kj::Promise<void>` 
to the member variable kj::TaskSet something isn't quite right.

My ideal situation would be this.
```
int main(int argc, const char** argv) {
    // setup event loop etc.
    auto io_context = kj::setupAsyncIO();
    // Instantiate a publisher that accepts incoming connections 
asynchronously.
    auto pub = Publisher<capnp::Text>("unix:/tmp/capnp-server-example", 
io_context);
    // Start publishing at a specific frequency. Implementation involves a 
kj::Timer with afterDelay().
    pub.publishAtFrequency("Hello Subscribers", 1);
    // Spin on this publisher. It should continue to accept new subscribers 
whilst publishing.
    pub.spin()
}
```

I hope I've given enough context and information. Please let me know if you 
need more information and thank you for this awesome library!

Dan


-- 
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/3de22823-a51e-48e3-b0f1-d7fcc9538930n%40googlegroups.com.

Reply via email to