Hi Mitsuo,

I recommend designing the interface like this:

interface EventPublisher{
    interface Subscriber {
        updateEvent @0 (event: Int32) -> ();
    }
    interface Subscription {}
    subscribe @0 (subscriber: Subscriber) -> (result: Int32, subscription:
Subscription);
    # To unsubscribe, drop the returned `subscription`.
}


Here, subscribe() returns a `subscription` object. This object has no
methods. But, when the capability is dropped, then the destructor will run
on the server side. Atn that point, you can remove the subscription.

A big advantage of this approach is that it handles connection failures
gracefully. If the client randomly disconnects, the `subscription`
capability is automatically dropped, thus unsubscribing the client. This
way you don't end up stuck sending messages to a disconnected subscriber.

It also solves your problem because you can remember arbitrary metadata
about the subscriber within the `Subscription` object, so you know what to
remove when it's destroyed.

-Kenton

On Mon, Nov 22, 2021 at 12:40 AM mitsuo <mitsuo.date@woven-planet.global>
wrote:

> Hi,
>
> I'm trying to implement pub/sub like communication model with the
> following scheme.
> *pubsub.capnp*
> *interface EventPublisher{*
> *    interface Subscriber {*
> *        updateEvent @0 (event: Int32) -> ();*
> *    }*
> *    subscribe @0 (subscriber: Subscriber) -> (result: Int32);*
> *    unsubscribe @1 (subscriber: Subscriber) -> (result: Int32);*
> *}*
>
> I'm using *kj::Vector<EventPublisher::Subscriber::Client> m_subscribers *to
> store the current subscribers.
> When I try to implement unsubscribe and remove the Subscriber from the
> Vector, I couldn't find good method to do that.
> Could you give me some advice?
>
> *server implementation*
> *class EventPublisherImpl final : public EventPublisher::Server {*
> * protected:*
> *  ::kj::Promise<void> subscribe(SubscribeContext context) {*
> *    cout << "subscribe request received" << endl;*
> *    m_subscribers.add(context.getParams().getSubscriber());*
> *    return kj::READY_NOW;*
> *  }*
>
> *  ::kj::Promise<void> unsubscribe(UnsubscribeContext context) {*
> *    cout << "unsubscribe request received" << endl;*
> *    auto unsub = context.getParams().getSubscriber();*
>
> *    // I want to remove usub from subscribers like
> m_subscribers[unsub].erase();*
> *    // But I couldn't find a method to compare*
> *    // "EventPublisher::Subscriber::Client" such as == operator or public
> method*
> *    // to distinguish the client.*
> *    //*
> *    // One solution is having an additional argument(id) for this purpose
> but*
> *    // that requres additional management of ID.*
> *    //  subscribe @0 (subscriber: Subscriber, id: Int32) -> (result:
> Int32);*
> *    //  unsubscribe @1 (id: Int32) -> (result: Int32);*
>
> *    // what I can do is erase everything but this is not my goal*
> *    m_subscribers.clear();*
> *    return kj::READY_NOW;*
> *  }*
>
> * private:*
> *  kj::Vector<EventPublisher::Subscriber::Client> m_subscribers;*
> *};*
> Thank you,
>
> --
> 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/26c4964f-21a2-4fe2-a410-7673786d40c9n%40googlegroups.com
> <https://groups.google.com/d/msgid/capnproto/26c4964f-21a2-4fe2-a410-7673786d40c9n%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%3DvDSdt-sWgDzEFody-5Y7x1XP9BrWVgOD5bwdh8Tunnw%40mail.gmail.com.

Reply via email to